9#include <qv4jscall_p.h>
10#include <qv4objectiterator_p.h>
21void Heap::UrlCtor::init(QV4::ExecutionEngine *engine)
23 Heap::FunctionObject::init(engine, QLatin1String(
"URL"));
26void UrlPrototype::init(ExecutionEngine *engine, Object *ctor)
31 ScopedObject o(scope);
33 defineDefaultProperty(QLatin1String(
"toString"), method_getHref);
34 defineDefaultProperty(QLatin1String(
"toJSON"), method_getHref);
36 defineAccessorProperty(QLatin1String(
"hash"), method_getHash, method_setHash);
37 defineAccessorProperty(QLatin1String(
"host"), method_getHost, method_setHost);
38 defineAccessorProperty(QLatin1String(
"hostname"), method_getHostname, method_setHostname);
39 defineAccessorProperty(QLatin1String(
"href"), method_getHref, method_setHref);
40 defineAccessorProperty(QLatin1String(
"origin"), method_getOrigin,
nullptr);
41 defineAccessorProperty(QLatin1String(
"password"), method_getPassword, method_setPassword);
42 defineAccessorProperty(QLatin1String(
"pathname"), method_getPathname, method_setPathname);
43 defineAccessorProperty(QLatin1String(
"port"), method_getPort, method_setPort);
44 defineAccessorProperty(QLatin1String(
"protocol"), method_getProtocol, method_setProtocol);
45 defineAccessorProperty(QLatin1String(
"search"), method_getSearch, method_setSearch);
46 defineAccessorProperty(QLatin1String(
"searchParams"), method_getSearchParams,
nullptr);
47 defineAccessorProperty(QLatin1String(
"username"), method_getUsername, method_setUsername);
50bool UrlObject::setHash(QString hash)
52 if (hash.startsWith(QLatin1Char(
'#')))
56 url.setFragment(hash);
61 d()->hash.set(engine(), engine()->newString(url.fragment()));
62 d()->href.set(engine(), engine()->newString(url.toString()));
67bool UrlObject::setHostname(QString host)
75 d()->hostname.set(engine(), engine()->newString(url.host()));
76 d()->href.set(engine(), engine()->newString(url.toString()));
84bool UrlObject::setHost(QString hostname)
88 if (hostname.contains(QLatin1Char(
':'))) {
89 const QStringList list = hostname.split(QLatin1Char(
':'));
91 port = list[1].toInt();
95 url.setHost(hostname);
101 if (url.port() != -1)
102 d()->port.set(engine(), engine()->newString(QString::number(url.port())));
104 d()->hostname.set(engine(), engine()->newString(url.host()));
105 d()->href.set(engine(), engine()->newString(url.toString()));
113bool UrlObject::setHref(QString href)
115 const QUrl url(href);
116 if (!url.isValid() || url.isRelative())
123void UrlObject::setUrl(
const QUrl &url)
125 d()->hash.set(engine(), engine()->newString(url.fragment()));
126 d()->hostname.set(engine(), engine()->newString(url.host()));
127 d()->href.set(engine(), engine()->newString(url.toString(QUrl::ComponentFormattingOptions(QUrl::ComponentFormattingOption::FullyEncoded))));
128 d()->password.set(engine(), engine()->newString(url.password()));
129 d()->pathname.set(engine(), engine()->newString(url.path()));
130 d()->port.set(engine(),
131 engine()->newString(url.port() == -1 ? QLatin1String(
"")
132 : QString::number(url.port())));
133 d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(
':')));
134 d()->search.set(engine(), engine()->newString(url.query(QUrl::ComponentFormattingOptions(QUrl::ComponentFormattingOption::FullyEncoded))));
135 d()->username.set(engine(), engine()->newString(url.userName()));
141bool UrlObject::setPassword(QString password)
144 url.setPassword(password);
149 d()->password.set(engine(), engine()->newString(url.password()));
150 d()->href.set(engine(), engine()->newString(url.toString()));
155bool UrlObject::setPathname(QString pathname)
158 url.setPath(pathname);
163 d()->pathname.set(engine(), engine()->newString(url.path()));
164 d()->href.set(engine(), engine()->newString(url.toString()));
169bool UrlObject::setPort(QString port)
172 url.setPort(port.isEmpty() ? -1 : port.toInt());
177 d()->port.set(engine(),
178 engine()->newString(url.port() == -1 ? QLatin1String(
"")
179 : QString::number(url.port())));
180 d()->href.set(engine(), engine()->newString(url.toString()));
188bool UrlObject::setProtocol(QString protocolOrScheme)
194 qsizetype firstColonPos = protocolOrScheme.indexOf(QLatin1Char(
':'));
196 if (firstColonPos != -1)
197 protocolOrScheme.truncate(firstColonPos);
199 url.setScheme(protocolOrScheme);
204 d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(
':')));
205 d()->href.set(engine(), engine()->newString(url.toString()));
213bool UrlObject::setSearch(QString search)
217 if (search.startsWith(QLatin1Char(
'?')))
218 search = search.mid(1);
220 url.setQuery(search);
225 d()->search.set(engine(), engine()->newString(url.query()));
226 d()->href.set(engine(), engine()->newString(url.toString()));
231bool UrlObject::setUsername(QString username)
234 url.setUserName(username);
239 d()->username.set(engine(), engine()->newString(url.userName()));
240 d()->href.set(engine(), engine()->newString(url.toString()));
245QString UrlObject::search()
const
247 auto url = QUrl(href());
248 if (
auto url = QUrl(href()); !url.hasQuery() || url.query().isEmpty())
249 return QLatin1String(
"");
251 constexpr auto options = QUrl::ComponentFormattingOption::EncodeSpaces
252 | QUrl::ComponentFormattingOption::EncodeUnicode
253 | QUrl::ComponentFormattingOption::EncodeReserved;
254 return u'?' + url.query(options);
257QUrl UrlObject::toQUrl()
const
262void UrlObject::updateOrigin()
266 QString proto = url.scheme();
269 if (proto == QLatin1String(
"blob")) {
270 url = QUrl(url.path());
271 proto = url.scheme();
275 if (proto == QLatin1String(
"http") || proto == QLatin1String(
"https")
276 || proto == QLatin1String(
"ftp")) {
277 origin = QLatin1String(
"%1://%2").arg(url.scheme(), url.host());
279 if (url.port() != -1)
280 origin.append(QLatin1String(
":") + QString::number(url.port()));
283 d()->origin.set(engine(), engine()->newString(origin));
286void UrlObject::updateHost()
290 QString host = url.host();
292 if (url.port() != -1)
293 host.append(QLatin1String(
":") + QString::number(url.port()));
295 d()->host.set(engine(), engine()->newString(host));
303 v4->throwTypeError(QStringLiteral(
"Value of \"this\" must be of type URL"));
307ReturnedValue UrlPrototype::method_getHash(
const FunctionObject *b,
const Value *thisObject,
310 ExecutionEngine *v4 = b->engine();
313 Scoped<UrlObject> r(scope, thisObject);
314 if (!checkUrlObjectType(v4, r))
315 return Encode::undefined();
317 return Encode(v4->newString(r->hash()));
320ReturnedValue UrlPrototype::method_setHash(
const FunctionObject *b,
const Value *thisObject,
321 const Value *argv,
int)
323 ExecutionEngine *v4 = b->engine();
326 ScopedValue arg(scope, argv[0]);
327 String *stringValue = arg->stringValue();
329 if (stringValue ==
nullptr)
330 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
332 Scoped<UrlObject> r(scope, thisObject);
333 if (!checkUrlObjectType(v4, r))
334 return Encode::undefined();
336 r->setHash(stringValue->toQString());
338 return Encode::undefined();
341ReturnedValue UrlPrototype::method_getHost(
const FunctionObject *b,
const Value *thisObject,
344 ExecutionEngine *v4 = b->engine();
347 Scoped<UrlObject> r(scope, thisObject);
348 if (!checkUrlObjectType(v4, r))
349 return Encode::undefined();
351 return Encode(v4->newString(r->host()));
354ReturnedValue UrlPrototype::method_setHost(
const FunctionObject *b,
const Value *thisObject,
355 const Value *argv,
int)
357 ExecutionEngine *v4 = b->engine();
360 ScopedValue arg(scope, argv[0]);
361 String *stringValue = arg->stringValue();
363 if (stringValue ==
nullptr)
364 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
366 Scoped<UrlObject> r(scope, thisObject);
367 if (!checkUrlObjectType(v4, r))
368 return Encode::undefined();
370 QString host = stringValue->toQString();
371 if (!r->setHost(host))
372 return v4->throwTypeError(QLatin1String(
"Invalid host: %1").arg(host));
374 return Encode::undefined();
377ReturnedValue UrlPrototype::method_getHostname(
const FunctionObject *b,
const Value *thisObject,
380 ExecutionEngine *v4 = b->engine();
383 Scoped<UrlObject> r(scope, thisObject);
384 if (!checkUrlObjectType(v4, r))
385 return Encode::undefined();
387 return Encode(v4->newString(r->hostname()));
390ReturnedValue UrlPrototype::method_setHostname(
const FunctionObject *b,
const Value *thisObject,
391 const Value *argv,
int)
393 ExecutionEngine *v4 = b->engine();
396 ScopedValue arg(scope, argv[0]);
397 String *stringValue = arg->stringValue();
399 if (stringValue ==
nullptr)
400 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
402 Scoped<UrlObject> r(scope, thisObject);
403 if (!checkUrlObjectType(v4, r))
404 return Encode::undefined();
406 QString hostname = stringValue->toQString();
407 if (!r->setHostname(hostname))
408 return v4->throwTypeError(QLatin1String(
"Invalid hostname: %1").arg(hostname));
410 return Encode::undefined();
413ReturnedValue UrlPrototype::method_getHref(
const FunctionObject *b,
const Value *thisObject,
416 ExecutionEngine *v4 = b->engine();
419 Scoped<UrlObject> r(scope, thisObject);
420 if (!checkUrlObjectType(v4, r))
421 return Encode::undefined();
423 return Encode(v4->newString(r->href()));
426ReturnedValue UrlPrototype::method_setHref(
const FunctionObject *b,
const Value *thisObject,
427 const Value *argv,
int)
429 ExecutionEngine *v4 = b->engine();
432 ScopedValue arg(scope, argv[0]);
433 String *stringValue = arg->stringValue();
435 if (stringValue ==
nullptr)
436 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
438 Scoped<UrlObject> r(scope, thisObject);
439 if (!checkUrlObjectType(v4, r))
440 return Encode::undefined();
442 QString href = stringValue->toQString();
443 if (!r->setHref(href))
444 return v4->throwTypeError(QLatin1String(
"Invalid URL: %1").arg(href));
446 return Encode::undefined();
449ReturnedValue UrlPrototype::method_getOrigin(
const FunctionObject *b,
const Value *thisObject,
452 ExecutionEngine *v4 = b->engine();
455 Scoped<UrlObject> r(scope, thisObject);
456 if (!checkUrlObjectType(v4, r))
457 return Encode::undefined();
459 return Encode(v4->newString(r->origin()));
462ReturnedValue UrlPrototype::method_getPassword(
const FunctionObject *b,
const Value *thisObject,
465 ExecutionEngine *v4 = b->engine();
468 Scoped<UrlObject> r(scope, thisObject);
469 if (!checkUrlObjectType(v4, r))
470 return Encode::undefined();
472 return Encode(v4->newString(r->password()));
475ReturnedValue UrlPrototype::method_setPassword(
const FunctionObject *b,
const Value *thisObject,
476 const Value *argv,
int)
478 ExecutionEngine *v4 = b->engine();
481 ScopedValue arg(scope, argv[0]);
482 String *stringValue = arg->stringValue();
484 if (stringValue ==
nullptr)
485 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
487 Scoped<UrlObject> r(scope, thisObject);
488 if (!checkUrlObjectType(v4, r))
489 return Encode::undefined();
491 r->setPassword(stringValue->toQString());
493 return Encode::undefined();
496ReturnedValue UrlPrototype::method_getPathname(
const FunctionObject *b,
const Value *thisObject,
499 ExecutionEngine *v4 = b->engine();
502 Scoped<UrlObject> r(scope, thisObject);
503 if (!checkUrlObjectType(v4, r))
504 return Encode::undefined();
506 return Encode(v4->newString(r->pathname()));
509ReturnedValue UrlPrototype::method_setPathname(
const FunctionObject *b,
const Value *thisObject,
510 const Value *argv,
int)
512 ExecutionEngine *v4 = b->engine();
515 ScopedValue arg(scope, argv[0]);
516 String *stringValue = arg->stringValue();
518 if (stringValue ==
nullptr)
519 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
521 Scoped<UrlObject> r(scope, thisObject);
522 if (!checkUrlObjectType(v4, r))
523 return Encode::undefined();
525 r->setPathname(stringValue->toQString());
527 return Encode::undefined();
530ReturnedValue UrlPrototype::method_getPort(
const FunctionObject *b,
const Value *thisObject,
533 ExecutionEngine *v4 = b->engine();
536 Scoped<UrlObject> r(scope, thisObject);
537 if (!checkUrlObjectType(v4, r))
538 return Encode::undefined();
540 return Encode(v4->newString(r->port()));
543ReturnedValue UrlPrototype::method_setPort(
const FunctionObject *b,
const Value *thisObject,
544 const Value *argv,
int)
546 ExecutionEngine *v4 = b->engine();
549 ScopedValue arg(scope, argv[0]);
550 String *stringValue = arg->stringValue();
554 if (stringValue !=
nullptr)
555 port = stringValue->toQString();
556 else if (arg->isInt32())
557 port = QString::number(arg->toInt32());
559 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
561 Scoped<UrlObject> r(scope, thisObject);
562 if (!checkUrlObjectType(v4, r))
563 return Encode::undefined();
565 if (!r->setPort(port))
566 return v4->throwTypeError(QLatin1String(
"Invalid port: %1").arg(port));
568 return Encode::undefined();
571ReturnedValue UrlPrototype::method_getProtocol(
const FunctionObject *b,
const Value *thisObject,
574 ExecutionEngine *v4 = b->engine();
577 Scoped<UrlObject> r(scope, thisObject);
578 if (!checkUrlObjectType(v4, r))
579 return Encode::undefined();
581 return Encode(v4->newString(r->protocol()));
584ReturnedValue UrlPrototype::method_setProtocol(
const FunctionObject *b,
const Value *thisObject,
585 const Value *argv,
int)
587 ExecutionEngine *v4 = b->engine();
590 ScopedValue arg(scope, argv[0]);
591 String *stringValue = arg->stringValue();
593 if (stringValue ==
nullptr)
594 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
596 Scoped<UrlObject> r(scope, thisObject);
597 if (!checkUrlObjectType(v4, r))
598 return Encode::undefined();
600 r->setProtocol(stringValue->toQString());
602 return Encode::undefined();
605ReturnedValue UrlPrototype::method_getSearch(
const FunctionObject *b,
const Value *thisObject,
608 ExecutionEngine *v4 = b->engine();
611 Scoped<UrlObject> r(scope, thisObject);
612 if (!checkUrlObjectType(v4, r))
613 return Encode::undefined();
615 return Encode(v4->newString(r->search()));
618ReturnedValue UrlPrototype::method_setSearch(
const FunctionObject *b,
const Value *thisObject,
619 const Value *argv,
int)
621 ExecutionEngine *v4 = b->engine();
624 ScopedValue arg(scope, argv[0]);
625 String *stringValue = arg->stringValue();
627 if (stringValue ==
nullptr)
628 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
630 Scoped<UrlObject> r(scope, thisObject);
631 if (!checkUrlObjectType(v4, r))
632 return Encode::undefined();
634 r->setSearch(stringValue->toQString());
636 return Encode::undefined();
639ReturnedValue UrlPrototype::method_getUsername(
const FunctionObject *b,
const Value *thisObject,
642 ExecutionEngine *v4 = b->engine();
645 Scoped<UrlObject> r(scope, thisObject);
646 if (!checkUrlObjectType(v4, r))
647 return Encode::undefined();
649 return Encode(v4->newString(r->username()));
652ReturnedValue UrlPrototype::method_setUsername(
const FunctionObject *b,
const Value *thisObject,
653 const Value *argv,
int)
655 ExecutionEngine *v4 = b->engine();
658 ScopedValue arg(scope, argv[0]);
659 String *stringValue = arg->stringValue();
661 if (stringValue ==
nullptr)
662 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
664 Scoped<UrlObject> r(scope, thisObject);
665 if (!checkUrlObjectType(v4, r))
666 return Encode::undefined();
668 r->setUsername(stringValue->toQString());
670 return Encode::undefined();
673ReturnedValue UrlPrototype::method_getSearchParams(
const FunctionObject *b,
const Value *thisObject,
676 ExecutionEngine *v4 = b->engine();
679 Scoped<UrlObject> r(scope, thisObject);
680 if (!checkUrlObjectType(v4, r))
681 return Encode::undefined();
683 Scoped<UrlSearchParamsObject> usp(scope, v4->newUrlSearchParamsObject());
685 usp->setUrlObject(thisObject->as<UrlObject>());
686 usp->initializeParams(r->search());
688 return usp->asReturnedValue();
691ReturnedValue UrlCtor::virtualCallAsConstructor(
const FunctionObject *that,
const Value *argv,
692 int argc,
const Value *newTarget)
694 ExecutionEngine *v4 = that->engine();
696 if (argc < 1 || argc > 2)
697 return v4->throwError(QLatin1String(
"Invalid amount of arguments"));
701 ScopedValue arg1(scope, argv[0]);
703 QString arg1String = arg1->toQString();
707 ScopedValue arg2(scope, argv[1]);
708 String *arg2StringValue = arg2->stringValue();
710 if (arg2StringValue ==
nullptr)
711 return v4->throwTypeError(QLatin1String(
"Invalid parameter provided"));
713 QUrl url = QUrl(arg2StringValue->toQString());
714 QUrl relativeUrl = QUrl(arg1String);
716 QString baseUrlPath = url.path();
717 QString relativePath = relativeUrl.path();
720 int lastSlash = baseUrlPath.lastIndexOf(QLatin1Char(
'/'));
722 baseUrlPath.truncate(lastSlash);
724 if (!relativePath.startsWith(QLatin1Char(
'/')))
725 relativePath = relativePath.prepend(QLatin1Char(
'/'));
727 url.setPath(baseUrlPath + relativePath);
728 url.setFragment(relativeUrl.fragment());
729 url.setQuery(relativeUrl.query());
731 urlString = url.toString();
733 urlString = arg1String;
736 ReturnedValue o = Encode(v4->newUrlObject());
741 ScopedObject obj(scope, o);
742 obj->setProtoFromNewTarget(newTarget);
744 UrlObject *urlObject = obj->as<UrlObject>();
746 if (!urlObject->setHref(urlString))
747 return v4->throwTypeError(QLatin1String(
"Invalid URL: %1").arg(urlString));
749 return obj->asReturnedValue();
753void Heap::UrlSearchParamsCtor::init(QV4::ExecutionEngine *engine)
755 Heap::FunctionObject::init(engine, QLatin1String(
"URLSearchParams"));
758void UrlSearchParamsPrototype::init(ExecutionEngine *engine, Object *ctor)
763 ScopedObject o(scope);
765 defineDefaultProperty(QLatin1String(
"toString"), method_toString);
766 defineDefaultProperty(QLatin1String(
"sort"), method_sort);
767 defineDefaultProperty(QLatin1String(
"append"), method_append);
768 defineDefaultProperty(QLatin1String(
"delete"), method_delete);
769 defineDefaultProperty(QLatin1String(
"has"), method_has);
770 defineDefaultProperty(QLatin1String(
"set"), method_set);
771 defineDefaultProperty(QLatin1String(
"get"), method_get);
772 defineDefaultProperty(QLatin1String(
"getAll"), method_getAll);
773 defineDefaultProperty(QLatin1String(
"forEach"), method_forEach);
774 defineDefaultProperty(QLatin1String(
"entries"), method_entries);
775 defineDefaultProperty(QLatin1String(
"keys"), method_keys);
776 defineDefaultProperty(QLatin1String(
"values"), method_values);
779ReturnedValue UrlSearchParamsCtor::virtualCallAsConstructor(
const FunctionObject *that,
const Value *argv,
780 int argc,
const Value *newTarget)
782 ExecutionEngine *v4 = that->engine();
785 return v4->throwError(QLatin1String(
"Invalid amount of arguments"));
789 ScopedValue arg(scope, argv[0]);
790 ArrayObject *argArrayObject = arg->as<ArrayObject>();
791 Object *argObject = arg->as<Object>();
793 ReturnedValue o = Encode(v4->newUrlSearchParamsObject());
798 ScopedObject obj(scope, o);
799 obj->setProtoFromNewTarget(newTarget);
801 UrlSearchParamsObject *urlSearchParamsObject = obj->as<UrlSearchParamsObject>();
803 if (argArrayObject !=
nullptr) {
804 ScopedArrayObject argArray(scope, argArrayObject);
806 uint len = argArray->getLength();
808 for (uint i = 0; i < len; i++) {
810 QV4::Value pair = Value::fromReturnedValue(argArray->get(i));
811 auto *pairArrayObject = pair.as<ArrayObject>();
813 if (pairArrayObject ==
nullptr) {
814 return v4->throwTypeError(
815 QLatin1String(
"element %1 is not a pair").arg(QString::number(i)));
819 ScopedArrayObject pairArray(scope, pairArrayObject);
822 uint pairLen = pairArray->getLength();
826 return v4->throwTypeError(QLatin1String(
"pair %1 has %2 elements instead of 2")
827 .arg(QString::number(i))
828 .arg(QString::number(pairLen)));
832 urlSearchParamsObject->initializeParams(argArray);
833 }
else if (argObject !=
nullptr) {
834 ScopedObject scopedObject(scope, argObject);
835 urlSearchParamsObject->initializeParams(scopedObject);
837 QString value = argc > 0 ? arg->toQString() : QLatin1String(
"");
838 urlSearchParamsObject->initializeParams(value);
841 return obj->asReturnedValue();
844void UrlSearchParamsObject::initializeParams()
846 auto *arrayObject = engine()->newArrayObject(0);
847 auto *keys = engine()->newArrayObject(0);
848 auto *values = engine()->newArrayObject(0);
850 d()->params.set(engine(), arrayObject);
851 d()->keys.set(engine(), keys);
852 d()->values.set(engine(), values);
855void UrlSearchParamsObject::initializeParams(QString value)
857 Q_ASSERT(d()->params ==
nullptr);
861 if (value.startsWith(QLatin1Char(
'?')))
862 value = value.mid(1);
864 const QStringList params = value.split(QLatin1Char(
'&'));
866 for (
const QString& param : params) {
872 int equalsIndex = param.indexOf(QLatin1Char(
'='));
873 if (equalsIndex != -1) {
874 key = param.left(equalsIndex);
875 value = param.mid(equalsIndex+1);
880 append(engine()->newString(key), engine()->newString(value));
884void UrlSearchParamsObject::initializeParams(ScopedArrayObject& params)
886 Q_ASSERT(d()->params ==
nullptr);
888 Scope scope(engine());
890 uint len = params->getLength();
891 auto *keys = engine()->newArrayObject(len);
892 auto *values = engine()->newArrayObject(len);
894 ScopedArrayObject scopedKeys(scope, keys);
895 ScopedArrayObject scopedValues(scope, values);
897 for (uint i = 0; i < len; i++)
902 QV4::Value pair = Value::fromReturnedValue(params->get(i));
903 auto *pairArrayObject = pair.as<ArrayObject>();
905 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
906 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(uint(1)));
908 scopedKeys->put(i, key);
909 scopedValues->put(i, value);
913 d()->params.set(engine(), params->d());
914 d()->keys.set(engine(), keys);
915 d()->values.set(engine(), values);
918void UrlSearchParamsObject::initializeParams(ScopedObject& params)
920 Q_ASSERT(d()->params ==
nullptr);
924 Scope scope(engine());
925 ObjectIterator it(scope, params, ObjectIterator::EnumerableOnly);
927 ScopedValue name(scope);
928 ScopedValue val(scope);
931 name = it.nextPropertyNameAsString(val);
935 Heap::String *nameStr = name->as<String>()->d();
936 Heap::String *valStr = val->toString(engine());
938 append(nameStr, valStr);
942void UrlSearchParamsObject::setParams(QList<QStringList> params)
944 auto *arrayObject = engine()->newArrayObject(0);
945 auto *keys = engine()->newArrayObject(0);
946 auto *values = engine()->newArrayObject(0);
948 Scope scope(engine());
950 ScopedArrayObject scopedArray(scope, arrayObject);
952 ScopedArrayObject scopedKeys(scope, keys);
953 ScopedArrayObject scopedValues(scope, values);
957 for (
const QStringList& param : params) {
959 auto *valuePair = engine()->newArrayObject(2);
961 ScopedArrayObject valuePairObject(scope, valuePair);
963 ScopedValue key(scope, Value::fromHeapObject(engine()->newString(param[0])));
964 ScopedValue value(scope, Value::fromHeapObject(engine()->newString(param[1])));
965 valuePairObject->put(uint(0), key);
966 valuePairObject->put(uint(1), value);
968 scopedKeys->put(len, key);
969 scopedValues->put(len, value);
971 scopedArray->put(len, valuePairObject);
975 d()->params.set(engine(), arrayObject);
976 d()->keys.set(engine(), keys);
977 d()->values.set(engine(), values);
980void UrlSearchParamsObject::setUrlObject(
const UrlObject *url)
982 d()->url.set(engine(), url->d());
985void UrlSearchParamsObject::append(Heap::String *name, Heap::String *value)
987 Scope scope(engine());
989 ScopedArrayObject scopedArray(scope, d()->params);
990 ScopedArrayObject scopedKeys(scope, d()->keys);
991 ScopedArrayObject scopedValues(scope, d()->values);
993 auto *valuePair = engine()->newArrayObject(2);
995 ScopedArrayObject valuePairObject(scope, valuePair);
997 ScopedValue keyScoped(scope, Value::fromHeapObject(name));
998 ScopedValue valueScoped(scope, Value::fromHeapObject(value));
999 valuePairObject->put(uint(0), keyScoped);
1000 valuePairObject->put(uint(1), valueScoped);
1002 uint len = scopedArray->getLength();
1004 scopedKeys->put(len, keyScoped);
1005 scopedValues->put(len, valueScoped);
1007 scopedArray->put(len, valuePairObject);
1010QList<QStringList> UrlSearchParamsObject::params()
const
1012 auto *arrayObject = d()->params.get();
1013 Scope scope(engine());
1014 ScopedArrayObject scopedArray(scope, arrayObject);
1016 QList<QStringList> result;
1018 uint len = scopedArray->getLength();
1020 for (uint i = 0; i < len; i++) {
1021 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(i));
1022 auto *pairArrayObject = pair.as<ArrayObject>();
1024 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
1025 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(uint(1)));
1027 result << QStringList { key.toQString(), value.toQString() };
1033Heap::UrlObject *UrlSearchParamsObject::urlObject()
const
1035 return d()->url.get();
1038QString UrlSearchParamsObject::searchString()
const
1040 QString search = QLatin1String(
"");
1041 auto params =
this->params();
1042 auto len = params.size();
1043 for (
int i = 0; i < len; ++i) {
1044 const QStringList ¶m = params[i];
1045 search += param[0] + QLatin1Char(
'=') + param[1];
1047 search += QLatin1Char(
'&');
1052int UrlSearchParamsObject::length()
const
1054 auto *arrayObject = d()->params.get();
1055 Scope scope(engine());
1056 ScopedArrayObject scopedArray(scope, arrayObject);
1058 return scopedArray->getLength();
1061int UrlSearchParamsObject::indexOf(QString name,
int last)
const
1063 auto *arrayObject = d()->params.get();
1064 Scope scope(engine());
1065 ScopedArrayObject scopedArray(scope, arrayObject);
1067 int len = scopedArray->getLength();
1069 for (
int i = last + 1; i < len; i++) {
1071 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(i));
1072 auto *pairArrayObject = pair.as<ArrayObject>();
1074 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
1076 if (key.toQString() == name)
1083QString UrlSearchParamsObject::stringAt(
int index,
int pairIndex)
const
1085 auto *arrayObject = d()->params.get();
1086 Scope scope(engine());
1087 ScopedArrayObject scopedArray(scope, arrayObject);
1089 if (index >= scopedArray->getLength())
1092 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(index));
1093 auto *pairArrayObject = pair.as<ArrayObject>();
1095 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(pairIndex));
1097 return value.toQString();
1100QV4::Heap::String * UrlSearchParamsObject::stringAtRaw(
int index,
int pairIndex)
const
1102 auto *arrayObject = d()->params.get();
1103 Scope scope(engine());
1104 ScopedArrayObject scopedArray(scope, arrayObject);
1106 if (index >= scopedArray->getLength())
1109 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(index));
1110 auto *pairArrayObject = pair.as<ArrayObject>();
1112 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(pairIndex));
1114 return value.as<String>()->d();
1117QString UrlSearchParamsObject::nameAt(
int index)
const
1119 return stringAt(index, 0);
1122QV4::Heap::String * UrlSearchParamsObject::nameAtRaw(
int index)
const
1124 return stringAtRaw(index, 0);
1128QString UrlSearchParamsObject::valueAt(
int index)
const
1130 return stringAt(index, 1);
1133QV4::Heap::String * UrlSearchParamsObject::valueAtRaw(
int index)
const
1135 return stringAtRaw(index, 1);
1143 PropertyAttributes *attrs =
nullptr)
override;
1147 PropertyAttributes *attrs)
1149 const UrlSearchParamsObject *usp =
static_cast<
const UrlSearchParamsObject *>(o);
1153 uint len = usp->length();
1154 if (arrayIndex < len) {
1155 uint index = arrayIndex;
1158 *attrs = Attr_NotConfigurable | Attr_NotWritable;
1160 pd->value = usp->engine()->newString(usp->nameAt(index));
1161 return PropertyKey::fromArrayIndex(index);
1164 return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
1167OwnPropertyKeyIterator *UrlSearchParamsObject::virtualOwnPropertyKeys(
const Object *m,
1171 return new UrlSearchParamsObjectOwnPropertyKeyIterator;
1174PropertyAttributes UrlSearchParamsObject::virtualGetOwnProperty(
const Managed *m, PropertyKey id,
1177 PropertyAttributes attributes = Object::virtualGetOwnProperty(m, id, p);
1178 if (attributes != Attr_Invalid)
1181 if (id.isArrayIndex()) {
1182 const int index = id.asArrayIndex();
1183 const auto usp =
static_cast<
const UrlSearchParamsObject *>(m);
1184 if (index < usp->length()) {
1186 p->value = usp->engine()->newString(usp->nameAt(index));
1187 return Attr_NotConfigurable | Attr_NotWritable;
1191 return Object::virtualGetOwnProperty(m, id, p);
1199 v4->throwTypeError(QStringLiteral(
"Value of \"this\" must be of type URLSearchParams"));
1203ReturnedValue UrlSearchParamsPrototype::method_toString(
1204 const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
1206 ExecutionEngine *v4 = b->engine();
1209 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1210 if (!checkSearchParamsType(v4, o))
1211 return Encode::undefined();
1213 auto params = o->params();
1217 for (
const QStringList &pair : params)
1218 value += QLatin1String(
"%1=%2&").arg(QString::fromUtf8(QUrl::toPercentEncoding(pair[0])),
1219 QString::fromUtf8(QUrl::toPercentEncoding(pair[1])));
1223 return Encode(v4->newString(value));
1226ReturnedValue UrlSearchParamsPrototype::method_sort(
const FunctionObject *b,
const Value *thisObject,
1229 ExecutionEngine *v4 = b->engine();
1232 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1233 if (!checkSearchParamsType(v4, o))
1234 return Encode::undefined();
1236 QList<QStringList> params = o->params();
1237 std::stable_sort(params.begin(), params.end(), [](QStringList a, QStringList b) {
return a[0] < b[0]; });
1239 o->setParams(params);
1241 return Encode::undefined();
1244ReturnedValue UrlSearchParamsPrototype::method_append(
const FunctionObject *b,
const Value *thisObject,
1245 const Value *argv,
int argc)
1247 ExecutionEngine *v4 = b->engine();
1251 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1253 ScopedValue argName(scope, argv[0]);
1254 ScopedValue argValue(scope, argv[1]);
1256 String *argNameString = argName->stringValue();
1258 if (argNameString ==
nullptr)
1259 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1261 ScopedString name(scope, argName->as<String>());
1262 ScopedString value(scope, argValue->toString(v4));
1264 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1265 if (!checkSearchParamsType(v4, o))
1266 return Encode::undefined();
1268 o->append(name->d(), value->d());
1270 return Encode::undefined();
1273ReturnedValue UrlSearchParamsPrototype::method_delete(
const FunctionObject *b,
const Value *thisObject,
1274 const Value *argv,
int argc)
1276 ExecutionEngine *v4 = b->engine();
1280 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1282 ScopedValue argName(scope, argv[0]);
1284 String *argNameString = argName->stringValue();
1286 if (argNameString ==
nullptr)
1287 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1289 QString name = argNameString->toQString();
1291 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1292 if (!checkSearchParamsType(v4, o))
1293 return Encode::undefined();
1295 QList<QStringList> params = o->params();
1296 params.removeIf([&name](
const auto &pair) {
return pair.at(0) == name; });
1298 o->setParams(params);
1300 return Encode::undefined();
1303ReturnedValue UrlSearchParamsPrototype::method_has(
const FunctionObject *b,
const Value *thisObject,
1304 const Value *argv,
int argc)
1306 ExecutionEngine *v4 = b->engine();
1310 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1312 ScopedValue argName(scope, argv[0]);
1314 String *argNameString = argName->stringValue();
1316 if (argNameString ==
nullptr)
1317 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1319 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1320 if (!checkSearchParamsType(v4, o))
1321 return Encode::undefined();
1323 QString name = argNameString->toQString();
1325 return Encode(o->indexOf(name) != -1);
1328ReturnedValue UrlSearchParamsPrototype::method_set(
const FunctionObject *b,
const Value *thisObject,
1329 const Value *argv,
int argc)
1331 ExecutionEngine *v4 = b->engine();
1335 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1337 ScopedValue argName(scope, argv[0]);
1338 ScopedValue argValue(scope, argv[1]);
1340 String *argNameString = argName->stringValue();
1342 if (argNameString ==
nullptr)
1343 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1345 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1346 if (!checkSearchParamsType(v4, o))
1347 return Encode::undefined();
1349 QString name = argNameString->toQString();
1350 QString value = argValue->toQString();
1352 auto params = o->params();
1354 bool matched =
false;
1356 for (
auto it = params.begin(); it != params.end();) {
1357 QStringList ¶m = *it;
1358 if (param[0] == name) {
1363 it = params.erase(it);
1371 params << QStringList { name, value };
1373 o->setParams(params);
1375 Scoped<UrlObject> scopedUrlObject(scope, o->d()->url.get());
1376 if (scopedUrlObject)
1377 scopedUrlObject->setSearch(o->searchString());
1379 return Encode::undefined();
1382ReturnedValue UrlSearchParamsPrototype::method_get(
const FunctionObject *b,
const Value *thisObject,
1383 const Value *argv,
int argc)
1385 ExecutionEngine *v4 = b->engine();
1389 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1391 ScopedValue argName(scope, argv[0]);
1393 String *argNameString = argName->stringValue();
1395 if (argNameString ==
nullptr)
1396 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1398 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1399 if (!checkSearchParamsType(v4, o))
1400 return Encode::undefined();
1402 QString name = argNameString->toQString();
1404 int index = o->indexOf(name);
1407 return Encode::null();
1409 return Encode(o->valueAtRaw(index));
1412ReturnedValue UrlSearchParamsPrototype::method_getAll(
const FunctionObject *b,
1413 const Value *thisObject,
const Value *argv,
1416 ExecutionEngine *v4 = b->engine();
1420 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1422 ScopedValue argName(scope, argv[0]);
1424 String *argNameString = argName->stringValue();
1426 if (argNameString ==
nullptr)
1427 return v4->throwTypeError(QLatin1String(
"Invalid argument provided"));
1429 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1430 if (!checkSearchParamsType(v4, o))
1431 return Encode::undefined();
1433 QString name = argNameString->toQString();
1435 auto *arrayObject = v4->newArrayObject(0);
1436 ScopedArrayObject result(scope, arrayObject);
1439 for (
int index = o->indexOf(name); index != -1; index = o->indexOf(name, index)) {
1440 ScopedValue value(scope, Value::fromHeapObject(o->valueAtRaw(index)));
1441 result->put(i++, value);
1444 return Encode(arrayObject);
1447ReturnedValue UrlSearchParamsPrototype::method_forEach(
const FunctionObject *b,
1448 const Value *thisObject,
const Value *argv,
1451 ExecutionEngine *v4 = b->engine();
1455 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1457 ScopedValue argFunc(scope, argv[0]);
1459 FunctionObject *func = argFunc->as<FunctionObject>();
1461 if (func ==
nullptr)
1462 return v4->throwTypeError(QLatin1String(
"Invalid argument: must be a function"));
1464 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1465 if (!checkSearchParamsType(v4, o))
1466 return Encode::undefined();
1468 for (
int i = 0; i < o->length(); i++) {
1469 Scoped<String> name(scope, o->nameAtRaw(i));
1470 Scoped<String> value(scope, o->valueAtRaw(i));
1472 QV4::JSCallArguments calldata(scope, 2);
1474 calldata.args[0] = value;
1475 calldata.args[1] = name;
1477 func->call(calldata);
1480 return Encode::undefined();
1483ReturnedValue UrlSearchParamsPrototype::method_entries(
const FunctionObject *b,
1484 const Value *thisObject,
const Value *,
1487 ExecutionEngine *v4 = b->engine();
1491 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1493 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1494 if (!checkSearchParamsType(v4, o))
1495 return Encode::undefined();
1497 ScopedObject params(scope, o->d()->params.get());
1499 Scoped<ArrayIteratorObject> paramsIterator(scope, v4->newArrayIteratorObject(params));
1500 paramsIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1501 return paramsIterator->asReturnedValue();
1504ReturnedValue UrlSearchParamsPrototype::method_keys(
const FunctionObject *b,
1505 const Value *thisObject,
const Value *,
1508 ExecutionEngine *v4 = b->engine();
1512 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1514 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1515 if (!checkSearchParamsType(v4, o))
1516 return Encode::undefined();
1518 ScopedObject keys(scope, o->d()->keys.get());
1520 Scoped<ArrayIteratorObject> keysIterator(scope, v4->newArrayIteratorObject(keys));
1521 keysIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1522 return keysIterator->asReturnedValue();
1525ReturnedValue UrlSearchParamsPrototype::method_values(
const FunctionObject *b,
1526 const Value *thisObject,
const Value *,
1529 ExecutionEngine *v4 = b->engine();
1533 return v4->throwError(QLatin1String(
"Bad amount of arguments"));
1535 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1536 if (!checkSearchParamsType(v4, o))
1537 return Encode::undefined();
1539 ScopedObject values(scope, o->d()->values.get());
1541 Scoped<ArrayIteratorObject> valuesIterator(scope, v4->newArrayIteratorObject(values));
1542 valuesIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1543 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)
PropertyKey next(const QV4::Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
~UrlSearchParamsObjectOwnPropertyKeyIterator() override=default