10#include <qv4jscall_p.h>
11#include <qv4objectiterator_p.h>
22void Heap::UrlCtor::init(QV4::ExecutionEngine *engine)
24 Heap::FunctionObject::init(engine, QLatin1String(
"URL"));
27void UrlPrototype::init(ExecutionEngine *engine, Object *ctor)
32 ScopedObject o(scope);
34 defineDefaultProperty(QLatin1String(
"toString"), method_getHref);
35 defineDefaultProperty(QLatin1String(
"toJSON"), method_getHref);
37 defineAccessorProperty(QLatin1String(
"hash"), method_getHash, method_setHash);
38 defineAccessorProperty(QLatin1String(
"host"), method_getHost, method_setHost);
39 defineAccessorProperty(QLatin1String(
"hostname"), method_getHostname, method_setHostname);
40 defineAccessorProperty(QLatin1String(
"href"), method_getHref, method_setHref);
41 defineAccessorProperty(QLatin1String(
"origin"), method_getOrigin,
nullptr);
42 defineAccessorProperty(QLatin1String(
"password"), method_getPassword, method_setPassword);
43 defineAccessorProperty(QLatin1String(
"pathname"), method_getPathname, method_setPathname);
44 defineAccessorProperty(QLatin1String(
"port"), method_getPort, method_setPort);
45 defineAccessorProperty(QLatin1String(
"protocol"), method_getProtocol, method_setProtocol);
46 defineAccessorProperty(QLatin1String(
"search"), method_getSearch, method_setSearch);
47 defineAccessorProperty(QLatin1String(
"searchParams"), method_getSearchParams,
nullptr);
48 defineAccessorProperty(QLatin1String(
"username"), method_getUsername, method_setUsername);
51bool UrlObject::setHash(QString hash)
53 if (hash.startsWith(QLatin1Char(
'#')))
57 url.setFragment(hash);
62 d()->hash.set(engine(), engine()->newString(url.fragment()));
63 d()->href.set(engine(), engine()->newString(url.toString()));
68bool UrlObject::setHostname(QString host)
76 d()->hostname.set(engine(), engine()->newString(url.host()));
77 d()->href.set(engine(), engine()->newString(url.toString()));
85bool UrlObject::setHost(QString hostname)
89 if (hostname.contains(QLatin1Char(
':'))) {
90 const QStringList list = hostname.split(QLatin1Char(
':'));
92 port = list[1].toInt();
96 url.setHost(hostname);
102 if (url.port() != -1)
103 d()->port.set(engine(), engine()->newString(QString::number(url.port())));
105 d()->hostname.set(engine(), engine()->newString(url.host()));
106 d()->href.set(engine(), engine()->newString(url.toString()));
114bool UrlObject::setHref(QString href)
116 const QUrl url(href);
117 if (!url.isValid() || url.isRelative())
124void UrlObject::setUrl(
const QUrl &url)
126 d()->hash.set(engine(), engine()->newString(url.fragment()));
127 d()->hostname.set(engine(), engine()->newString(url.host()));
128 d()->href.set(engine(), engine()->newString(url.toString(QUrl::ComponentFormattingOptions(QUrl::ComponentFormattingOption::FullyEncoded))));
129 d()->password.set(engine(), engine()->newString(url.password()));
130 d()->pathname.set(engine(), engine()->newString(url.path()));
131 d()->port.set(engine(),
132 engine()->newString(url.port() == -1 ? QLatin1String(
"")
133 : QString::number(url.port())));
134 d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(
':')));
135 d()->search.set(engine(), engine()->newString(url.query(QUrl::ComponentFormattingOptions(QUrl::ComponentFormattingOption::FullyEncoded))));
136 d()->username.set(engine(), engine()->newString(url.userName()));
142bool UrlObject::setPassword(QString password)
145 url.setPassword(password);
150 d()->password.set(engine(), engine()->newString(url.password()));
151 d()->href.set(engine(), engine()->newString(url.toString()));
156bool UrlObject::setPathname(QString pathname)
159 url.setPath(pathname);
164 d()->pathname.set(engine(), engine()->newString(url.path()));
165 d()->href.set(engine(), engine()->newString(url.toString()));
170bool UrlObject::setPort(QString port)
173 url.setPort(port.isEmpty() ? -1 : port.toInt());
178 d()->port.set(engine(),
179 engine()->newString(url.port() == -1 ? QLatin1String(
"")
180 : QString::number(url.port())));
181 d()->href.set(engine(), engine()->newString(url.toString()));
189bool UrlObject::setProtocol(QString protocolOrScheme)
195 qsizetype firstColonPos = protocolOrScheme.indexOf(QLatin1Char(
':'));
197 if (firstColonPos != -1)
198 protocolOrScheme.truncate(firstColonPos);
200 url.setScheme(protocolOrScheme);
205 d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(
':')));
206 d()->href.set(engine(), engine()->newString(url.toString()));
214bool UrlObject::setSearch(QString search)
218 if (search.startsWith(QLatin1Char(
'?'))) {
219 search = search.mid(1);
220 }
else if (search.isEmpty()) {
227 url.setQuery(search);
232 d()->search.set(engine(), engine()->newString(url.query()));
233 d()->href.set(engine(), engine()->newString(url.toString()));
238bool UrlObject::setUsername(QString username)
241 url.setUserName(username);
246 d()->username.set(engine(), engine()->newString(url.userName()));
247 d()->href.set(engine(), engine()->newString(url.toString()));
252QString UrlObject::search()
const
254 auto url = QUrl(href());
255 if (
auto url = QUrl(href()); !url.hasQuery() || url.query().isEmpty())
256 return QLatin1String(
"");
258 constexpr auto options = QUrl::ComponentFormattingOption::EncodeSpaces
259 | QUrl::ComponentFormattingOption::EncodeUnicode
260 | QUrl::ComponentFormattingOption::EncodeReserved;
261 return u'?' + url.query(options);
264QUrl UrlObject::toQUrl()
const
269void UrlObject::updateOrigin()
273 QString proto = url.scheme();
276 if (proto == QLatin1String(
"blob")) {
277 url = QUrl(url.path());
278 proto = url.scheme();
282 if (proto == QLatin1String(
"http") || proto == QLatin1String(
"https")
283 || proto == QLatin1String(
"ftp")) {
284 origin = QLatin1String(
"%1://%2").arg(url.scheme(), url.host());
286 if (url.port() != -1)
287 origin.append(QLatin1String(
":") + QString::number(url.port()));
290 d()->origin.set(engine(), engine()->newString(origin));
293void UrlObject::updateHost()
297 QString host = url.host();
299 if (url.port() != -1)
300 host.append(QLatin1String(
":") + QString::number(url.port()));
302 d()->host.set(engine(), engine()->newString(host));
310 v4->throwTypeError(QStringLiteral(
"Value of \"this\" must be of type URL"));
314ReturnedValue UrlPrototype::method_getHash(
const FunctionObject *b,
const Value *thisObject,
317 ExecutionEngine *v4 = b->engine();
320 Scoped<UrlObject> r(scope, thisObject);
321 if (!checkUrlObjectType(v4, r))
322 return Encode::undefined();
324 return Encode(v4->newString(r->hash()));
327ReturnedValue UrlPrototype::method_setHash(
const FunctionObject *b,
const Value *thisObject,
328 const Value *argv,
int)
330 ExecutionEngine *v4 = b->engine();
333 ScopedValue arg(scope, argv[0]);
334 String *stringValue = arg->stringValue();
336 if (stringValue ==
nullptr)
337 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
339 Scoped<UrlObject> r(scope, thisObject);
340 if (!checkUrlObjectType(v4, r))
341 return Encode::undefined();
343 r->setHash(stringValue->toQString());
345 return Encode::undefined();
348ReturnedValue UrlPrototype::method_getHost(
const FunctionObject *b,
const Value *thisObject,
351 ExecutionEngine *v4 = b->engine();
354 Scoped<UrlObject> r(scope, thisObject);
355 if (!checkUrlObjectType(v4, r))
356 return Encode::undefined();
358 return Encode(v4->newString(r->host()));
361ReturnedValue UrlPrototype::method_setHost(
const FunctionObject *b,
const Value *thisObject,
362 const Value *argv,
int)
364 ExecutionEngine *v4 = b->engine();
367 ScopedValue arg(scope, argv[0]);
368 String *stringValue = arg->stringValue();
370 if (stringValue ==
nullptr)
371 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
373 Scoped<UrlObject> r(scope, thisObject);
374 if (!checkUrlObjectType(v4, r))
375 return Encode::undefined();
377 QString host = stringValue->toQString();
378 if (!r->setHost(host))
379 return v4->throwTypeError(QLatin1String(
"Invalid host: %1").arg(host));
381 return Encode::undefined();
384ReturnedValue UrlPrototype::method_getHostname(
const FunctionObject *b,
const Value *thisObject,
387 ExecutionEngine *v4 = b->engine();
390 Scoped<UrlObject> r(scope, thisObject);
391 if (!checkUrlObjectType(v4, r))
392 return Encode::undefined();
394 return Encode(v4->newString(r->hostname()));
397ReturnedValue UrlPrototype::method_setHostname(
const FunctionObject *b,
const Value *thisObject,
398 const Value *argv,
int)
400 ExecutionEngine *v4 = b->engine();
403 ScopedValue arg(scope, argv[0]);
404 String *stringValue = arg->stringValue();
406 if (stringValue ==
nullptr)
407 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
409 Scoped<UrlObject> r(scope, thisObject);
410 if (!checkUrlObjectType(v4, r))
411 return Encode::undefined();
413 QString hostname = stringValue->toQString();
414 if (!r->setHostname(hostname))
415 return v4->throwTypeError(QLatin1String(
"Invalid hostname: %1").arg(hostname));
417 return Encode::undefined();
420ReturnedValue UrlPrototype::method_getHref(
const FunctionObject *b,
const Value *thisObject,
423 ExecutionEngine *v4 = b->engine();
426 Scoped<UrlObject> r(scope, thisObject);
427 if (!checkUrlObjectType(v4, r))
428 return Encode::undefined();
430 return Encode(v4->newString(r->href()));
433ReturnedValue UrlPrototype::method_setHref(
const FunctionObject *b,
const Value *thisObject,
434 const Value *argv,
int)
436 ExecutionEngine *v4 = b->engine();
439 ScopedValue arg(scope, argv[0]);
440 String *stringValue = arg->stringValue();
442 if (stringValue ==
nullptr)
443 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
445 Scoped<UrlObject> r(scope, thisObject);
446 if (!checkUrlObjectType(v4, r))
447 return Encode::undefined();
449 QString href = stringValue->toQString();
450 if (!r->setHref(href))
451 return v4->throwTypeError(QLatin1String(
"Invalid URL: %1").arg(href));
453 return Encode::undefined();
456ReturnedValue UrlPrototype::method_getOrigin(
const FunctionObject *b,
const Value *thisObject,
459 ExecutionEngine *v4 = b->engine();
462 Scoped<UrlObject> r(scope, thisObject);
463 if (!checkUrlObjectType(v4, r))
464 return Encode::undefined();
466 return Encode(v4->newString(r->origin()));
469ReturnedValue UrlPrototype::method_getPassword(
const FunctionObject *b,
const Value *thisObject,
472 ExecutionEngine *v4 = b->engine();
475 Scoped<UrlObject> r(scope, thisObject);
476 if (!checkUrlObjectType(v4, r))
477 return Encode::undefined();
479 return Encode(v4->newString(r->password()));
482ReturnedValue UrlPrototype::method_setPassword(
const FunctionObject *b,
const Value *thisObject,
483 const Value *argv,
int)
485 ExecutionEngine *v4 = b->engine();
488 ScopedValue arg(scope, argv[0]);
489 String *stringValue = arg->stringValue();
491 if (stringValue ==
nullptr)
492 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
494 Scoped<UrlObject> r(scope, thisObject);
495 if (!checkUrlObjectType(v4, r))
496 return Encode::undefined();
498 r->setPassword(stringValue->toQString());
500 return Encode::undefined();
503ReturnedValue UrlPrototype::method_getPathname(
const FunctionObject *b,
const Value *thisObject,
506 ExecutionEngine *v4 = b->engine();
509 Scoped<UrlObject> r(scope, thisObject);
510 if (!checkUrlObjectType(v4, r))
511 return Encode::undefined();
513 return Encode(v4->newString(r->pathname()));
516ReturnedValue UrlPrototype::method_setPathname(
const FunctionObject *b,
const Value *thisObject,
517 const Value *argv,
int)
519 ExecutionEngine *v4 = b->engine();
522 ScopedValue arg(scope, argv[0]);
523 String *stringValue = arg->stringValue();
525 if (stringValue ==
nullptr)
526 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
528 Scoped<UrlObject> r(scope, thisObject);
529 if (!checkUrlObjectType(v4, r))
530 return Encode::undefined();
532 r->setPathname(stringValue->toQString());
534 return Encode::undefined();
537ReturnedValue UrlPrototype::method_getPort(
const FunctionObject *b,
const Value *thisObject,
540 ExecutionEngine *v4 = b->engine();
543 Scoped<UrlObject> r(scope, thisObject);
544 if (!checkUrlObjectType(v4, r))
545 return Encode::undefined();
547 return Encode(v4->newString(r->port()));
550ReturnedValue UrlPrototype::method_setPort(
const FunctionObject *b,
const Value *thisObject,
551 const Value *argv,
int)
553 ExecutionEngine *v4 = b->engine();
556 ScopedValue arg(scope, argv[0]);
557 String *stringValue = arg->stringValue();
561 if (stringValue !=
nullptr)
562 port = stringValue->toQString();
563 else if (arg->isInt32())
564 port = QString::number(arg->toInt32());
566 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
568 Scoped<UrlObject> r(scope, thisObject);
569 if (!checkUrlObjectType(v4, r))
570 return Encode::undefined();
572 if (!r->setPort(port))
573 return v4->throwTypeError(QLatin1String(
"Invalid port: %1").arg(port));
575 return Encode::undefined();
578ReturnedValue UrlPrototype::method_getProtocol(
const FunctionObject *b,
const Value *thisObject,
581 ExecutionEngine *v4 = b->engine();
584 Scoped<UrlObject> r(scope, thisObject);
585 if (!checkUrlObjectType(v4, r))
586 return Encode::undefined();
588 return Encode(v4->newString(r->protocol()));
591ReturnedValue UrlPrototype::method_setProtocol(
const FunctionObject *b,
const Value *thisObject,
592 const Value *argv,
int)
594 ExecutionEngine *v4 = b->engine();
597 ScopedValue arg(scope, argv[0]);
598 String *stringValue = arg->stringValue();
600 if (stringValue ==
nullptr)
601 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
603 Scoped<UrlObject> r(scope, thisObject);
604 if (!checkUrlObjectType(v4, r))
605 return Encode::undefined();
607 r->setProtocol(stringValue->toQString());
609 return Encode::undefined();
612ReturnedValue UrlPrototype::method_getSearch(
const FunctionObject *b,
const Value *thisObject,
615 ExecutionEngine *v4 = b->engine();
618 Scoped<UrlObject> r(scope, thisObject);
619 if (!checkUrlObjectType(v4, r))
620 return Encode::undefined();
622 return Encode(v4->newString(r->search()));
625ReturnedValue UrlPrototype::method_setSearch(
const FunctionObject *b,
const Value *thisObject,
626 const Value *argv,
int)
628 ExecutionEngine *v4 = b->engine();
631 ScopedValue arg(scope, argv[0]);
632 String *stringValue = arg->stringValue();
634 if (stringValue ==
nullptr)
635 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
637 Scoped<UrlObject> r(scope, thisObject);
638 if (!checkUrlObjectType(v4, r))
639 return Encode::undefined();
641 r->setSearch(stringValue->toQString());
643 return Encode::undefined();
646ReturnedValue UrlPrototype::method_getUsername(
const FunctionObject *b,
const Value *thisObject,
649 ExecutionEngine *v4 = b->engine();
652 Scoped<UrlObject> r(scope, thisObject);
653 if (!checkUrlObjectType(v4, r))
654 return Encode::undefined();
656 return Encode(v4->newString(r->username()));
659ReturnedValue UrlPrototype::method_setUsername(
const FunctionObject *b,
const Value *thisObject,
660 const Value *argv,
int)
662 ExecutionEngine *v4 = b->engine();
665 ScopedValue arg(scope, argv[0]);
666 String *stringValue = arg->stringValue();
668 if (stringValue ==
nullptr)
669 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
671 Scoped<UrlObject> r(scope, thisObject);
672 if (!checkUrlObjectType(v4, r))
673 return Encode::undefined();
675 r->setUsername(stringValue->toQString());
677 return Encode::undefined();
680ReturnedValue UrlPrototype::method_getSearchParams(
const FunctionObject *b,
const Value *thisObject,
683 ExecutionEngine *v4 = b->engine();
686 Scoped<UrlObject> r(scope, thisObject);
687 if (!checkUrlObjectType(v4, r))
688 return Encode::undefined();
690 Scoped<UrlSearchParamsObject> usp(scope, v4->newUrlSearchParamsObject());
692 usp->setUrlObject(thisObject->as<UrlObject>());
693 usp->initializeParams(r->search());
695 return usp->asReturnedValue();
698ReturnedValue UrlCtor::virtualCallAsConstructor(
const FunctionObject *that,
const Value *argv,
699 int argc,
const Value *newTarget)
701 ExecutionEngine *v4 = that->engine();
703 if (argc < 1 || argc > 2)
704 return v4->throwError(QLatin1String(
"Invalid amount of arguments"));
708 ScopedValue arg1(scope, argv[0]);
710 QString arg1String = arg1->toQString();
714 ScopedValue arg2(scope, argv[1]);
715 String *arg2StringValue = arg2->stringValue();
717 if (arg2StringValue ==
nullptr)
718 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
720 QUrl url = QUrl(arg2StringValue->toQString());
721 QUrl relativeUrl = QUrl(arg1String);
723 QString baseUrlPath = url.path();
724 QString relativePath = relativeUrl.path();
727 int lastSlash = baseUrlPath.lastIndexOf(QLatin1Char(
'/'));
729 baseUrlPath.truncate(lastSlash);
731 if (!relativePath.startsWith(QLatin1Char(
'/')))
732 relativePath = relativePath.prepend(QLatin1Char(
'/'));
734 url.setPath(baseUrlPath + relativePath);
735 url.setFragment(relativeUrl.fragment());
736 url.setQuery(relativeUrl.query());
738 urlString = url.toString();
740 urlString = arg1String;
743 ReturnedValue o = Encode(v4->newUrlObject());
748 ScopedObject obj(scope, o);
749 obj->setProtoFromNewTarget(newTarget);
751 UrlObject *urlObject = obj->as<UrlObject>();
753 if (!urlObject->setHref(urlString))
754 return v4->throwTypeError(QLatin1String(
"Invalid URL: %1").arg(urlString));
756 return obj->asReturnedValue();
760void Heap::UrlSearchParamsCtor::init(QV4::ExecutionEngine *engine)
762 Heap::FunctionObject::init(engine, QLatin1String(
"URLSearchParams"));
765void UrlSearchParamsPrototype::init(ExecutionEngine *engine, Object *ctor)
770 ScopedObject o(scope);
772 defineDefaultProperty(QLatin1String(
"toString"), method_toString);
773 defineDefaultProperty(QLatin1String(
"sort"), method_sort);
774 defineDefaultProperty(QLatin1String(
"append"), method_append);
775 defineDefaultProperty(QLatin1String(
"delete"), method_delete);
776 defineDefaultProperty(QLatin1String(
"has"), method_has);
777 defineDefaultProperty(QLatin1String(
"set"), method_set);
778 defineDefaultProperty(QLatin1String(
"get"), method_get);
779 defineDefaultProperty(QLatin1String(
"getAll"), method_getAll);
780 defineDefaultProperty(QLatin1String(
"forEach"), method_forEach);
781 defineDefaultProperty(QLatin1String(
"entries"), method_entries);
782 defineDefaultProperty(QLatin1String(
"keys"), method_keys);
783 defineDefaultProperty(QLatin1String(
"values"), method_values);
786ReturnedValue UrlSearchParamsCtor::virtualCallAsConstructor(
const FunctionObject *that,
const Value *argv,
787 int argc,
const Value *newTarget)
789 ExecutionEngine *v4 = that->engine();
792 return v4->throwError(QLatin1String(
"Invalid amount of arguments"));
796 ScopedValue arg(scope, argv[0]);
797 ArrayObject *argArrayObject = arg->as<ArrayObject>();
798 Object *argObject = arg->as<Object>();
800 ReturnedValue o = Encode(v4->newUrlSearchParamsObject());
805 ScopedObject obj(scope, o);
806 obj->setProtoFromNewTarget(newTarget);
808 UrlSearchParamsObject *urlSearchParamsObject = obj->as<UrlSearchParamsObject>();
810 if (argArrayObject !=
nullptr) {
811 ScopedArrayObject argArray(scope, argArrayObject);
813 uint len = argArray->getLength();
815 for (uint i = 0; i < len; i++) {
817 QV4::Value pair = Value::fromReturnedValue(argArray->get(i));
818 auto *pairArrayObject = pair.as<ArrayObject>();
820 if (pairArrayObject ==
nullptr) {
821 return v4->throwTypeError(
822 QLatin1String(
"element %1 is not a pair").arg(QString::number(i)));
826 ScopedArrayObject pairArray(scope, pairArrayObject);
829 uint pairLen = pairArray->getLength();
833 return v4->throwTypeError(QLatin1String(
"pair %1 has %2 elements instead of 2")
834 .arg(QString::number(i))
835 .arg(QString::number(pairLen)));
839 urlSearchParamsObject->initializeParams(argArray);
840 }
else if (argObject !=
nullptr) {
841 ScopedObject scopedObject(scope, argObject);
842 urlSearchParamsObject->initializeParams(scopedObject);
844 QString value = argc > 0 ? arg->toQString() : QLatin1String(
"");
845 urlSearchParamsObject->initializeParams(value);
848 return obj->asReturnedValue();
851void UrlSearchParamsObject::initializeParams()
853 auto *arrayObject = engine()->newArrayObject(0);
854 auto *keys = engine()->newArrayObject(0);
855 auto *values = engine()->newArrayObject(0);
857 d()->params.set(engine(), arrayObject);
858 d()->keys.set(engine(), keys);
859 d()->values.set(engine(), values);
862void UrlSearchParamsObject::initializeParams(QString value)
864 Q_ASSERT(d()->params ==
nullptr);
868 if (value.startsWith(QLatin1Char(
'?')))
869 value = value.mid(1);
871 const QStringList params = value.split(QLatin1Char(
'&'));
873 for (
const QString& param : params) {
879 int equalsIndex = param.indexOf(QLatin1Char(
'='));
880 if (equalsIndex != -1) {
881 key = param.left(equalsIndex);
882 value = param.mid(equalsIndex+1);
887 append(engine()->newString(key), engine()->newString(value));
891void UrlSearchParamsObject::initializeParams(ScopedArrayObject& params)
893 Q_ASSERT(d()->params ==
nullptr);
895 Scope scope(engine());
897 uint len = params->getLength();
898 auto *keys = engine()->newArrayObject(len);
899 auto *values = engine()->newArrayObject(len);
901 ScopedArrayObject scopedKeys(scope, keys);
902 ScopedArrayObject scopedValues(scope, values);
904 for (uint i = 0; i < len; i++)
909 QV4::Value pair = Value::fromReturnedValue(params->get(i));
910 auto *pairArrayObject = pair.as<ArrayObject>();
912 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
913 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(uint(1)));
915 scopedKeys->put(i, key);
916 scopedValues->put(i, value);
920 d()->params.set(engine(), params->d());
921 d()->keys.set(engine(), keys);
922 d()->values.set(engine(), values);
925void UrlSearchParamsObject::initializeParams(ScopedObject& params)
927 Q_ASSERT(d()->params ==
nullptr);
931 Scope scope(engine());
932 ObjectIterator it(scope, params, ObjectIterator::EnumerableOnly);
934 ScopedValue name(scope);
935 ScopedValue val(scope);
938 name = it.nextPropertyNameAsString(val);
942 Heap::String *nameStr = name->as<String>()->d();
943 Heap::String *valStr = val->toString(engine());
945 append(nameStr, valStr);
949void UrlSearchParamsObject::setParams(QList<QStringList> params)
951 auto *arrayObject = engine()->newArrayObject(0);
952 auto *keys = engine()->newArrayObject(0);
953 auto *values = engine()->newArrayObject(0);
955 Scope scope(engine());
957 ScopedArrayObject scopedArray(scope, arrayObject);
959 ScopedArrayObject scopedKeys(scope, keys);
960 ScopedArrayObject scopedValues(scope, values);
964 for (
const QStringList& param : params) {
966 auto *valuePair = engine()->newArrayObject(2);
968 ScopedArrayObject valuePairObject(scope, valuePair);
970 ScopedValue key(scope, Value::fromHeapObject(engine()->newString(param[0])));
971 ScopedValue value(scope, Value::fromHeapObject(engine()->newString(param[1])));
972 valuePairObject->put(uint(0), key);
973 valuePairObject->put(uint(1), value);
975 scopedKeys->put(len, key);
976 scopedValues->put(len, value);
978 scopedArray->put(len, valuePairObject);
982 d()->params.set(engine(), arrayObject);
983 d()->keys.set(engine(), keys);
984 d()->values.set(engine(), values);
987void UrlSearchParamsObject::setUrlObject(
const UrlObject *url)
989 d()->url.set(engine(), url->d());
992void UrlSearchParamsObject::append(Heap::String *name, Heap::String *value)
994 Scope scope(engine());
996 ScopedArrayObject scopedArray(scope, d()->params);
997 ScopedArrayObject scopedKeys(scope, d()->keys);
998 ScopedArrayObject scopedValues(scope, d()->values);
1000 auto *valuePair = engine()->newArrayObject(2);
1002 ScopedArrayObject valuePairObject(scope, valuePair);
1004 ScopedValue keyScoped(scope, Value::fromHeapObject(name));
1005 ScopedValue valueScoped(scope, Value::fromHeapObject(value));
1006 valuePairObject->put(uint(0), keyScoped);
1007 valuePairObject->put(uint(1), valueScoped);
1009 uint len = scopedArray->getLength();
1011 scopedKeys->put(len, keyScoped);
1012 scopedValues->put(len, valueScoped);
1014 scopedArray->put(len, valuePairObject);
1017QList<QStringList> UrlSearchParamsObject::params()
const
1019 auto *arrayObject = d()->params.get();
1020 Scope scope(engine());
1021 ScopedArrayObject scopedArray(scope, arrayObject);
1023 QList<QStringList> result;
1025 uint len = scopedArray->getLength();
1027 for (uint i = 0; i < len; i++) {
1028 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(i));
1029 auto *pairArrayObject = pair.as<ArrayObject>();
1031 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
1032 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(uint(1)));
1034 result << QStringList { key.toQString(), value.toQString() };
1040Heap::UrlObject *UrlSearchParamsObject::urlObject()
const
1042 return d()->url.get();
1045QString UrlSearchParamsObject::searchString()
const
1047 QString search = QLatin1String(
"");
1048 auto params =
this->params();
1049 auto len = params.size();
1050 for (
int i = 0; i < len; ++i) {
1051 const QStringList ¶m = params[i];
1052 search += param[0] + QLatin1Char(
'=') + param[1];
1054 search += QLatin1Char(
'&');
1059int UrlSearchParamsObject::length()
const
1061 auto *arrayObject = d()->params.get();
1062 Scope scope(engine());
1063 ScopedArrayObject scopedArray(scope, arrayObject);
1065 return scopedArray->getLength();
1068int UrlSearchParamsObject::indexOf(QString name,
int last)
const
1070 auto *arrayObject = d()->params.get();
1071 Scope scope(engine());
1072 ScopedArrayObject scopedArray(scope, arrayObject);
1074 int len = scopedArray->getLength();
1076 for (
int i = last + 1; i < len; i++) {
1078 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(i));
1079 auto *pairArrayObject = pair.as<ArrayObject>();
1081 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
1083 if (key.toQString() == name)
1090QString UrlSearchParamsObject::stringAt(
int index,
int pairIndex)
const
1092 auto *arrayObject = d()->params.get();
1093 Scope scope(engine());
1094 ScopedArrayObject scopedArray(scope, arrayObject);
1096 if (index >= scopedArray->getLength())
1099 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(index));
1100 auto *pairArrayObject = pair.as<ArrayObject>();
1102 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(pairIndex));
1104 return value.toQString();
1107QV4::Heap::String * UrlSearchParamsObject::stringAtRaw(
int index,
int pairIndex)
const
1109 auto *arrayObject = d()->params.get();
1110 Scope scope(engine());
1111 ScopedArrayObject scopedArray(scope, arrayObject);
1113 if (index >= scopedArray->getLength())
1116 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(index));
1117 auto *pairArrayObject = pair.as<ArrayObject>();
1119 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(pairIndex));
1121 return value.as<String>()->d();
1124QString UrlSearchParamsObject::nameAt(
int index)
const
1126 return stringAt(index, 0);
1129QV4::Heap::String * UrlSearchParamsObject::nameAtRaw(
int index)
const
1131 return stringAtRaw(index, 0);
1135QString UrlSearchParamsObject::valueAt(
int index)
const
1137 return stringAt(index, 1);
1140QV4::Heap::String * UrlSearchParamsObject::valueAtRaw(
int index)
const
1142 return stringAtRaw(index, 1);
1146struct UrlSearchParamsObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
1148 ~UrlSearchParamsObjectOwnPropertyKeyIterator() override =
default;
1149 PropertyKey next(
const QV4::Object *o, Property *pd =
nullptr,
1150 PropertyAttributes *attrs =
nullptr)
override;
1154PropertyKey UrlSearchParamsObjectOwnPropertyKeyIterator::next(
const QV4::Object *o, Property *pd,
1155 PropertyAttributes *attrs)
1157 const UrlSearchParamsObject *usp =
static_cast<
const UrlSearchParamsObject *>(o);
1161 uint len = usp->length();
1162 if (arrayIndex < len) {
1163 uint index = arrayIndex;
1166 *attrs = Attr_NotConfigurable | Attr_NotWritable;
1168 pd->value = usp->engine()->newString(usp->nameAt(index));
1169 return PropertyKey::fromArrayIndex(index);
1172 return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
1175OwnPropertyKeyIterator *UrlSearchParamsObject::virtualOwnPropertyKeys(
const Object *m,
1179 return new UrlSearchParamsObjectOwnPropertyKeyIterator;
1182PropertyAttributes UrlSearchParamsObject::virtualGetOwnProperty(
const Managed *m, PropertyKey id,
1185 PropertyAttributes attributes = Object::virtualGetOwnProperty(m, id, p);
1186 if (attributes != Attr_Invalid)
1189 if (id.isArrayIndex()) {
1190 const int index = id.asArrayIndex();
1191 const auto usp =
static_cast<
const UrlSearchParamsObject *>(m);
1192 if (index < usp->length()) {
1194 p->value = usp->engine()->newString(usp->nameAt(index));
1195 return Attr_NotConfigurable | Attr_NotWritable;
1199 return Object::virtualGetOwnProperty(m, id, p);
1207 v4->throwTypeError(QStringLiteral(
"Value of \"this\" must be of type URLSearchParams"));
1211ReturnedValue UrlSearchParamsPrototype::method_toString(
1212 const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
1214 ExecutionEngine *v4 = b->engine();
1217 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1218 if (!checkSearchParamsType(v4, o))
1219 return Encode::undefined();
1221 auto params = o->params();
1225 for (
const QStringList &pair : params)
1226 value += QLatin1String(
"%1=%2&").arg(QString::fromUtf8(QUrl::toPercentEncoding(pair[0])),
1227 QString::fromUtf8(QUrl::toPercentEncoding(pair[1])));
1231 return Encode(v4->newString(value));
1234ReturnedValue UrlSearchParamsPrototype::method_sort(
const FunctionObject *b,
const Value *thisObject,
1237 ExecutionEngine *v4 = b->engine();
1240 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1241 if (!checkSearchParamsType(v4, o))
1242 return Encode::undefined();
1244 QList<QStringList> params = o->params();
1245 std::stable_sort(params.begin(), params.end(), [](QStringList a, QStringList b) {
return a[0] < b[0]; });
1247 o->setParams(params);
1249 return Encode::undefined();
1252ReturnedValue UrlSearchParamsPrototype::method_append(
const FunctionObject *b,
const Value *thisObject,
1253 const Value *argv,
int argc)
1255 ExecutionEngine *v4 = b->engine();
1259 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1261 ScopedValue argName(scope, argv[0]);
1262 ScopedValue argValue(scope, argv[1]);
1264 String *argNameString = argName->stringValue();
1266 if (argNameString ==
nullptr)
1267 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1269 ScopedString name(scope, argName->as<String>());
1270 ScopedString value(scope, argValue->toString(v4));
1272 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1273 if (!checkSearchParamsType(v4, o))
1274 return Encode::undefined();
1276 o->append(name->d(), value->d());
1278 return Encode::undefined();
1281ReturnedValue UrlSearchParamsPrototype::method_delete(
const FunctionObject *b,
const Value *thisObject,
1282 const Value *argv,
int argc)
1284 ExecutionEngine *v4 = b->engine();
1288 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1290 ScopedValue argName(scope, argv[0]);
1292 String *argNameString = argName->stringValue();
1294 if (argNameString ==
nullptr)
1295 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1297 QString name = argNameString->toQString();
1299 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1300 if (!checkSearchParamsType(v4, o))
1301 return Encode::undefined();
1303 QList<QStringList> params = o->params();
1304 params.removeIf([&name](
const auto &pair) {
return pair.at(0) == name; });
1306 o->setParams(params);
1308 return Encode::undefined();
1311ReturnedValue UrlSearchParamsPrototype::method_has(
const FunctionObject *b,
const Value *thisObject,
1312 const Value *argv,
int argc)
1314 ExecutionEngine *v4 = b->engine();
1318 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1320 ScopedValue argName(scope, argv[0]);
1322 String *argNameString = argName->stringValue();
1324 if (argNameString ==
nullptr)
1325 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1327 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1328 if (!checkSearchParamsType(v4, o))
1329 return Encode::undefined();
1331 QString name = argNameString->toQString();
1333 return Encode(o->indexOf(name) != -1);
1336ReturnedValue UrlSearchParamsPrototype::method_set(
const FunctionObject *b,
const Value *thisObject,
1337 const Value *argv,
int argc)
1339 ExecutionEngine *v4 = b->engine();
1343 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1345 ScopedValue argName(scope, argv[0]);
1346 ScopedValue argValue(scope, argv[1]);
1348 String *argNameString = argName->stringValue();
1350 if (argNameString ==
nullptr)
1351 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1353 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1354 if (!checkSearchParamsType(v4, o))
1355 return Encode::undefined();
1357 QString name = argNameString->toQString();
1358 QString value = argValue->toQString();
1360 auto params = o->params();
1362 bool matched =
false;
1364 for (
auto it = params.begin(); it != params.end();) {
1365 QStringList ¶m = *it;
1366 if (param[0] == name) {
1371 it = params.erase(it);
1379 params << QStringList { name, value };
1381 o->setParams(params);
1383 Scoped<UrlObject> scopedUrlObject(scope, o->d()->url.get());
1384 if (scopedUrlObject)
1385 scopedUrlObject->setSearch(o->searchString());
1387 return Encode::undefined();
1390ReturnedValue UrlSearchParamsPrototype::method_get(
const FunctionObject *b,
const Value *thisObject,
1391 const Value *argv,
int argc)
1393 ExecutionEngine *v4 = b->engine();
1397 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1399 ScopedValue argName(scope, argv[0]);
1401 String *argNameString = argName->stringValue();
1403 if (argNameString ==
nullptr)
1404 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1406 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1407 if (!checkSearchParamsType(v4, o))
1408 return Encode::undefined();
1410 QString name = argNameString->toQString();
1412 int index = o->indexOf(name);
1415 return Encode::null();
1417 return Encode(o->valueAtRaw(index));
1420ReturnedValue UrlSearchParamsPrototype::method_getAll(
const FunctionObject *b,
1421 const Value *thisObject,
const Value *argv,
1424 ExecutionEngine *v4 = b->engine();
1428 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1430 ScopedValue argName(scope, argv[0]);
1432 String *argNameString = argName->stringValue();
1434 if (argNameString ==
nullptr)
1435 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1437 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1438 if (!checkSearchParamsType(v4, o))
1439 return Encode::undefined();
1441 QString name = argNameString->toQString();
1443 auto *arrayObject = v4->newArrayObject(0);
1444 ScopedArrayObject result(scope, arrayObject);
1447 for (
int index = o->indexOf(name); index != -1; index = o->indexOf(name, index)) {
1448 ScopedValue value(scope, Value::fromHeapObject(o->valueAtRaw(index)));
1449 result->put(i++, value);
1452 return Encode(arrayObject);
1455ReturnedValue UrlSearchParamsPrototype::method_forEach(
const FunctionObject *b,
1456 const Value *thisObject,
const Value *argv,
1459 ExecutionEngine *v4 = b->engine();
1463 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1465 ScopedValue argFunc(scope, argv[0]);
1467 FunctionObject *func = argFunc->as<FunctionObject>();
1469 if (func ==
nullptr)
1470 return v4->throwTypeError(QLatin1String(
"Invalid argument: must be a function"));
1472 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1473 if (!checkSearchParamsType(v4, o))
1474 return Encode::undefined();
1476 for (
int i = 0; i < o->length(); i++) {
1477 Scoped<String> name(scope, o->nameAtRaw(i));
1478 Scoped<String> value(scope, o->valueAtRaw(i));
1480 QV4::JSCallArguments calldata(scope, 2);
1482 calldata.args[0] = value;
1483 calldata.args[1] = name;
1485 func->call(calldata);
1488 return Encode::undefined();
1491ReturnedValue UrlSearchParamsPrototype::method_entries(
const FunctionObject *b,
1492 const Value *thisObject,
const Value *,
1495 ExecutionEngine *v4 = b->engine();
1499 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1501 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1502 if (!checkSearchParamsType(v4, o))
1503 return Encode::undefined();
1505 ScopedObject params(scope, o->d()->params.get());
1507 Scoped<ArrayIteratorObject> paramsIterator(scope, v4->newArrayIteratorObject(params));
1508 paramsIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1509 return paramsIterator->asReturnedValue();
1512ReturnedValue UrlSearchParamsPrototype::method_keys(
const FunctionObject *b,
1513 const Value *thisObject,
const Value *,
1516 ExecutionEngine *v4 = b->engine();
1520 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1522 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1523 if (!checkSearchParamsType(v4, o))
1524 return Encode::undefined();
1526 ScopedObject keys(scope, o->d()->keys.get());
1528 Scoped<ArrayIteratorObject> keysIterator(scope, v4->newArrayIteratorObject(keys));
1529 keysIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1530 return keysIterator->asReturnedValue();
1533ReturnedValue UrlSearchParamsPrototype::method_values(
const FunctionObject *b,
1534 const Value *thisObject,
const Value *,
1537 ExecutionEngine *v4 = b->engine();
1541 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1543 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1544 if (!checkSearchParamsType(v4, o))
1545 return Encode::undefined();
1547 ScopedObject values(scope, o->d()->values.get());
1549 Scoped<ArrayIteratorObject> valuesIterator(scope, v4->newArrayIteratorObject(values));
1550 valuesIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1551 return valuesIterator->asReturnedValue();
DEFINE_OBJECT_VTABLE(UrlCtor)
DEFINE_OBJECT_VTABLE(UrlSearchParamsObject)
DEFINE_OBJECT_VTABLE(UrlSearchParamsCtor)
static bool checkSearchParamsType(ExecutionEngine *v4, const Scoped< UrlSearchParamsObject > &o)
static bool checkUrlObjectType(ExecutionEngine *v4, const Scoped< UrlObject > &r)
DEFINE_OBJECT_VTABLE(UrlObject)