Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4urlobject.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// Qt-Security score:significant
4
7
8#include <QtCore/QUrl>
9
10#include <qv4jscall_p.h>
11#include <qv4objectiterator_p.h>
12
13using namespace QV4;
14
17
20
21
22void Heap::UrlCtor::init(QV4::ExecutionEngine *engine)
23{
24 Heap::FunctionObject::init(engine, QLatin1String("URL"));
25}
26
27void UrlPrototype::init(ExecutionEngine *engine, Object *ctor)
28{
29 Q_UNUSED(ctor);
30
31 Scope scope(engine);
32 ScopedObject o(scope);
33
34 defineDefaultProperty(QLatin1String("toString"), method_getHref);
35 defineDefaultProperty(QLatin1String("toJSON"), method_getHref);
36
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);
49}
50
51bool UrlObject::setHash(QString hash)
52{
53 if (hash.startsWith(QLatin1Char('#')))
54 hash = hash.mid(1);
55
56 QUrl url = toQUrl();
57 url.setFragment(hash);
58
59 if (!url.isValid())
60 return false;
61
62 d()->hash.set(engine(), engine()->newString(url.fragment()));
63 d()->href.set(engine(), engine()->newString(url.toString()));
64
65 return true;
66}
67
68bool UrlObject::setHostname(QString host)
69{
70 QUrl url = toQUrl();
71 url.setHost(host);
72
73 if (!url.isValid())
74 return false;
75
76 d()->hostname.set(engine(), engine()->newString(url.host()));
77 d()->href.set(engine(), engine()->newString(url.toString()));
78
79 updateOrigin();
80 updateHost();
81
82 return true;
83}
84
85bool UrlObject::setHost(QString hostname)
86{
87 int port = -1;
88
89 if (hostname.contains(QLatin1Char(':'))) {
90 const QStringList list = hostname.split(QLatin1Char(':'));
91 hostname = list[0];
92 port = list[1].toInt();
93 }
94
95 QUrl url = toQUrl();
96 url.setHost(hostname);
97 url.setPort(port);
98
99 if (!url.isValid())
100 return false;
101
102 if (url.port() != -1)
103 d()->port.set(engine(), engine()->newString(QString::number(url.port())));
104
105 d()->hostname.set(engine(), engine()->newString(url.host()));
106 d()->href.set(engine(), engine()->newString(url.toString()));
107
108 updateOrigin();
109 updateHost();
110
111 return true;
112}
113
114bool UrlObject::setHref(QString href)
115{
116 const QUrl url(href);
117 if (!url.isValid() || url.isRelative())
118 return false;
119
120 setUrl(url);
121 return true;
122}
123
124void UrlObject::setUrl(const QUrl &url)
125{
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()));
137
138 updateOrigin();
139 updateHost();
140}
141
142bool UrlObject::setPassword(QString password)
143{
144 QUrl url = toQUrl();
145 url.setPassword(password);
146
147 if (!url.isValid())
148 return false;
149
150 d()->password.set(engine(), engine()->newString(url.password()));
151 d()->href.set(engine(), engine()->newString(url.toString()));
152
153 return true;
154}
155
156bool UrlObject::setPathname(QString pathname)
157{
158 QUrl url = toQUrl();
159 url.setPath(pathname);
160
161 if (!url.isValid())
162 return false;
163
164 d()->pathname.set(engine(), engine()->newString(url.path()));
165 d()->href.set(engine(), engine()->newString(url.toString()));
166
167 return true;
168}
169
170bool UrlObject::setPort(QString port)
171{
172 QUrl url = toQUrl();
173 url.setPort(port.isEmpty() ? -1 : port.toInt());
174
175 if (!url.isValid())
176 return false;
177
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()));
182
183 updateOrigin();
184 updateHost();
185
186 return true;
187}
188
189bool UrlObject::setProtocol(QString protocolOrScheme)
190{
191 QUrl url = toQUrl();
192 // If there is one or several ':' in the protocolOrScheme,
193 // everything from the first colon is removed.
194
195 qsizetype firstColonPos = protocolOrScheme.indexOf(QLatin1Char(':'));
196
197 if (firstColonPos != -1)
198 protocolOrScheme.truncate(firstColonPos);
199
200 url.setScheme(protocolOrScheme);
201
202 if (!url.isValid())
203 return false;
204
205 d()->protocol.set(engine(), engine()->newString(url.scheme() + QLatin1Char(':')));
206 d()->href.set(engine(), engine()->newString(url.toString()));
207
208 updateOrigin();
209 updateHost();
210
211 return true;
212}
213
214bool UrlObject::setSearch(QString search)
215{
216 QUrl url = toQUrl();
217
218 if (search.startsWith(QLatin1Char('?'))) {
219 search = search.mid(1);
220 } else if (search.isEmpty()) {
221 // In JS, setting an empty query removes the '?' as well. QUrl only does that for a null QString.
222 // The way to get a lone '?' in JS is to set the search property to "?". That is why this is in
223 // the else branch.
224 search = QString(); // it's null now
225 }
226
227 url.setQuery(search);
228
229 if (!url.isValid())
230 return false;
231
232 d()->search.set(engine(), engine()->newString(url.query()));
233 d()->href.set(engine(), engine()->newString(url.toString()));
234
235 return true;
236}
237
238bool UrlObject::setUsername(QString username)
239{
240 QUrl url = toQUrl();
241 url.setUserName(username);
242
243 if (!url.isValid())
244 return false;
245
246 d()->username.set(engine(), engine()->newString(url.userName()));
247 d()->href.set(engine(), engine()->newString(url.toString()));
248
249 return true;
250}
251
252QString UrlObject::search() const
253{
254 auto url = QUrl(href());
255 if (auto url = QUrl(href()); !url.hasQuery() || url.query().isEmpty())
256 return QLatin1String("");
257
258 constexpr auto options = QUrl::ComponentFormattingOption::EncodeSpaces
259 | QUrl::ComponentFormattingOption::EncodeUnicode
260 | QUrl::ComponentFormattingOption::EncodeReserved;
261 return u'?' + url.query(options);
262}
263
264QUrl UrlObject::toQUrl() const
265{
266 return QUrl(href());
267}
268
269void UrlObject::updateOrigin()
270{
271 QUrl url = toQUrl();
272
273 QString proto = url.scheme();
274
275 // A blob's origin is the origin of the URL that it points to
276 if (proto == QLatin1String("blob")) {
277 url = QUrl(url.path());
278 proto = url.scheme();
279 }
280
281 QString origin;
282 if (proto == QLatin1String("http") || proto == QLatin1String("https")
283 || proto == QLatin1String("ftp")) {
284 origin = QLatin1String("%1://%2").arg(url.scheme(), url.host());
285
286 if (url.port() != -1)
287 origin.append(QLatin1String(":") + QString::number(url.port()));
288 }
289
290 d()->origin.set(engine(), engine()->newString(origin));
291}
292
293void UrlObject::updateHost()
294{
295 QUrl url = toQUrl();
296
297 QString host = url.host();
298
299 if (url.port() != -1)
300 host.append(QLatin1String(":") + QString::number(url.port()));
301
302 d()->host.set(engine(), engine()->newString(host));
303}
304
305static bool checkUrlObjectType(ExecutionEngine *v4, const Scoped<UrlObject> &r)
306{
307 if (r)
308 return true;
309
310 v4->throwTypeError(QStringLiteral("Value of \"this\" must be of type URL"));
311 return false;
312}
313
314ReturnedValue UrlPrototype::method_getHash(const FunctionObject *b, const Value *thisObject,
315 const Value *, int)
316{
317 ExecutionEngine *v4 = b->engine();
318 Scope scope(v4);
319
320 Scoped<UrlObject> r(scope, thisObject);
321 if (!checkUrlObjectType(v4, r))
322 return Encode::undefined();
323
324 return Encode(v4->newString(r->hash()));
325}
326
327ReturnedValue UrlPrototype::method_setHash(const FunctionObject *b, const Value *thisObject,
328 const Value *argv, int)
329{
330 ExecutionEngine *v4 = b->engine();
331 Scope scope(v4);
332
333 ScopedValue arg(scope, argv[0]);
334 String *stringValue = arg->stringValue();
335
336 if (stringValue == nullptr)
337 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
338
339 Scoped<UrlObject> r(scope, thisObject);
340 if (!checkUrlObjectType(v4, r))
341 return Encode::undefined();
342
343 r->setHash(stringValue->toQString());
344
345 return Encode::undefined();
346}
347
348ReturnedValue UrlPrototype::method_getHost(const FunctionObject *b, const Value *thisObject,
349 const Value *, int)
350{
351 ExecutionEngine *v4 = b->engine();
352 Scope scope(v4);
353
354 Scoped<UrlObject> r(scope, thisObject);
355 if (!checkUrlObjectType(v4, r))
356 return Encode::undefined();
357
358 return Encode(v4->newString(r->host()));
359}
360
361ReturnedValue UrlPrototype::method_setHost(const FunctionObject *b, const Value *thisObject,
362 const Value *argv, int)
363{
364 ExecutionEngine *v4 = b->engine();
365 Scope scope(v4);
366
367 ScopedValue arg(scope, argv[0]);
368 String *stringValue = arg->stringValue();
369
370 if (stringValue == nullptr)
371 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
372
373 Scoped<UrlObject> r(scope, thisObject);
374 if (!checkUrlObjectType(v4, r))
375 return Encode::undefined();
376
377 QString host = stringValue->toQString();
378 if (!r->setHost(host))
379 return v4->throwTypeError(QLatin1String("Invalid host: %1").arg(host));
380
381 return Encode::undefined();
382}
383
384ReturnedValue UrlPrototype::method_getHostname(const FunctionObject *b, const Value *thisObject,
385 const Value *, int)
386{
387 ExecutionEngine *v4 = b->engine();
388 Scope scope(v4);
389
390 Scoped<UrlObject> r(scope, thisObject);
391 if (!checkUrlObjectType(v4, r))
392 return Encode::undefined();
393
394 return Encode(v4->newString(r->hostname()));
395}
396
397ReturnedValue UrlPrototype::method_setHostname(const FunctionObject *b, const Value *thisObject,
398 const Value *argv, int)
399{
400 ExecutionEngine *v4 = b->engine();
401 Scope scope(v4);
402
403 ScopedValue arg(scope, argv[0]);
404 String *stringValue = arg->stringValue();
405
406 if (stringValue == nullptr)
407 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
408
409 Scoped<UrlObject> r(scope, thisObject);
410 if (!checkUrlObjectType(v4, r))
411 return Encode::undefined();
412
413 QString hostname = stringValue->toQString();
414 if (!r->setHostname(hostname))
415 return v4->throwTypeError(QLatin1String("Invalid hostname: %1").arg(hostname));
416
417 return Encode::undefined();
418}
419
420ReturnedValue UrlPrototype::method_getHref(const FunctionObject *b, const Value *thisObject,
421 const Value *, int)
422{
423 ExecutionEngine *v4 = b->engine();
424 Scope scope(v4);
425
426 Scoped<UrlObject> r(scope, thisObject);
427 if (!checkUrlObjectType(v4, r))
428 return Encode::undefined();
429
430 return Encode(v4->newString(r->href()));
431}
432
433ReturnedValue UrlPrototype::method_setHref(const FunctionObject *b, const Value *thisObject,
434 const Value *argv, int)
435{
436 ExecutionEngine *v4 = b->engine();
437 Scope scope(v4);
438
439 ScopedValue arg(scope, argv[0]);
440 String *stringValue = arg->stringValue();
441
442 if (stringValue == nullptr)
443 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
444
445 Scoped<UrlObject> r(scope, thisObject);
446 if (!checkUrlObjectType(v4, r))
447 return Encode::undefined();
448
449 QString href = stringValue->toQString();
450 if (!r->setHref(href))
451 return v4->throwTypeError(QLatin1String("Invalid URL: %1").arg(href));
452
453 return Encode::undefined();
454}
455
456ReturnedValue UrlPrototype::method_getOrigin(const FunctionObject *b, const Value *thisObject,
457 const Value *, int)
458{
459 ExecutionEngine *v4 = b->engine();
460 Scope scope(v4);
461
462 Scoped<UrlObject> r(scope, thisObject);
463 if (!checkUrlObjectType(v4, r))
464 return Encode::undefined();
465
466 return Encode(v4->newString(r->origin()));
467}
468
469ReturnedValue UrlPrototype::method_getPassword(const FunctionObject *b, const Value *thisObject,
470 const Value *, int)
471{
472 ExecutionEngine *v4 = b->engine();
473 Scope scope(v4);
474
475 Scoped<UrlObject> r(scope, thisObject);
476 if (!checkUrlObjectType(v4, r))
477 return Encode::undefined();
478
479 return Encode(v4->newString(r->password()));
480}
481
482ReturnedValue UrlPrototype::method_setPassword(const FunctionObject *b, const Value *thisObject,
483 const Value *argv, int)
484{
485 ExecutionEngine *v4 = b->engine();
486 Scope scope(v4);
487
488 ScopedValue arg(scope, argv[0]);
489 String *stringValue = arg->stringValue();
490
491 if (stringValue == nullptr)
492 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
493
494 Scoped<UrlObject> r(scope, thisObject);
495 if (!checkUrlObjectType(v4, r))
496 return Encode::undefined();
497
498 r->setPassword(stringValue->toQString());
499
500 return Encode::undefined();
501}
502
503ReturnedValue UrlPrototype::method_getPathname(const FunctionObject *b, const Value *thisObject,
504 const Value *, int)
505{
506 ExecutionEngine *v4 = b->engine();
507 Scope scope(v4);
508
509 Scoped<UrlObject> r(scope, thisObject);
510 if (!checkUrlObjectType(v4, r))
511 return Encode::undefined();
512
513 return Encode(v4->newString(r->pathname()));
514}
515
516ReturnedValue UrlPrototype::method_setPathname(const FunctionObject *b, const Value *thisObject,
517 const Value *argv, int)
518{
519 ExecutionEngine *v4 = b->engine();
520 Scope scope(v4);
521
522 ScopedValue arg(scope, argv[0]);
523 String *stringValue = arg->stringValue();
524
525 if (stringValue == nullptr)
526 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
527
528 Scoped<UrlObject> r(scope, thisObject);
529 if (!checkUrlObjectType(v4, r))
530 return Encode::undefined();
531
532 r->setPathname(stringValue->toQString());
533
534 return Encode::undefined();
535}
536
537ReturnedValue UrlPrototype::method_getPort(const FunctionObject *b, const Value *thisObject,
538 const Value *, int)
539{
540 ExecutionEngine *v4 = b->engine();
541 Scope scope(v4);
542
543 Scoped<UrlObject> r(scope, thisObject);
544 if (!checkUrlObjectType(v4, r))
545 return Encode::undefined();
546
547 return Encode(v4->newString(r->port()));
548}
549
550ReturnedValue UrlPrototype::method_setPort(const FunctionObject *b, const Value *thisObject,
551 const Value *argv, int)
552{
553 ExecutionEngine *v4 = b->engine();
554 Scope scope(v4);
555
556 ScopedValue arg(scope, argv[0]);
557 String *stringValue = arg->stringValue();
558
559 QString port;
560
561 if (stringValue != nullptr)
562 port = stringValue->toQString();
563 else if (arg->isInt32())
564 port = QString::number(arg->toInt32());
565 else
566 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
567
568 Scoped<UrlObject> r(scope, thisObject);
569 if (!checkUrlObjectType(v4, r))
570 return Encode::undefined();
571
572 if (!r->setPort(port))
573 return v4->throwTypeError(QLatin1String("Invalid port: %1").arg(port));
574
575 return Encode::undefined();
576}
577
578ReturnedValue UrlPrototype::method_getProtocol(const FunctionObject *b, const Value *thisObject,
579 const Value *, int)
580{
581 ExecutionEngine *v4 = b->engine();
582 Scope scope(v4);
583
584 Scoped<UrlObject> r(scope, thisObject);
585 if (!checkUrlObjectType(v4, r))
586 return Encode::undefined();
587
588 return Encode(v4->newString(r->protocol()));
589}
590
591ReturnedValue UrlPrototype::method_setProtocol(const FunctionObject *b, const Value *thisObject,
592 const Value *argv, int)
593{
594 ExecutionEngine *v4 = b->engine();
595 Scope scope(v4);
596
597 ScopedValue arg(scope, argv[0]);
598 String *stringValue = arg->stringValue();
599
600 if (stringValue == nullptr)
601 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
602
603 Scoped<UrlObject> r(scope, thisObject);
604 if (!checkUrlObjectType(v4, r))
605 return Encode::undefined();
606
607 r->setProtocol(stringValue->toQString());
608
609 return Encode::undefined();
610}
611
612ReturnedValue UrlPrototype::method_getSearch(const FunctionObject *b, const Value *thisObject,
613 const Value *, int)
614{
615 ExecutionEngine *v4 = b->engine();
616 Scope scope(v4);
617
618 Scoped<UrlObject> r(scope, thisObject);
619 if (!checkUrlObjectType(v4, r))
620 return Encode::undefined();
621
622 return Encode(v4->newString(r->search()));
623}
624
625ReturnedValue UrlPrototype::method_setSearch(const FunctionObject *b, const Value *thisObject,
626 const Value *argv, int)
627{
628 ExecutionEngine *v4 = b->engine();
629 Scope scope(v4);
630
631 ScopedValue arg(scope, argv[0]);
632 String *stringValue = arg->stringValue();
633
634 if (stringValue == nullptr)
635 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
636
637 Scoped<UrlObject> r(scope, thisObject);
638 if (!checkUrlObjectType(v4, r))
639 return Encode::undefined();
640
641 r->setSearch(stringValue->toQString());
642
643 return Encode::undefined();
644}
645
646ReturnedValue UrlPrototype::method_getUsername(const FunctionObject *b, const Value *thisObject,
647 const Value *, int)
648{
649 ExecutionEngine *v4 = b->engine();
650 Scope scope(v4);
651
652 Scoped<UrlObject> r(scope, thisObject);
653 if (!checkUrlObjectType(v4, r))
654 return Encode::undefined();
655
656 return Encode(v4->newString(r->username()));
657}
658
659ReturnedValue UrlPrototype::method_setUsername(const FunctionObject *b, const Value *thisObject,
660 const Value *argv, int)
661{
662 ExecutionEngine *v4 = b->engine();
663 Scope scope(v4);
664
665 ScopedValue arg(scope, argv[0]);
666 String *stringValue = arg->stringValue();
667
668 if (stringValue == nullptr)
669 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
670
671 Scoped<UrlObject> r(scope, thisObject);
672 if (!checkUrlObjectType(v4, r))
673 return Encode::undefined();
674
675 r->setUsername(stringValue->toQString());
676
677 return Encode::undefined();
678}
679
680ReturnedValue UrlPrototype::method_getSearchParams(const FunctionObject *b, const Value *thisObject,
681 const Value *, int)
682{
683 ExecutionEngine *v4 = b->engine();
684 Scope scope(v4);
685
686 Scoped<UrlObject> r(scope, thisObject);
687 if (!checkUrlObjectType(v4, r))
688 return Encode::undefined();
689
690 Scoped<UrlSearchParamsObject> usp(scope, v4->newUrlSearchParamsObject());
691
692 usp->setUrlObject(thisObject->as<UrlObject>());
693 usp->initializeParams(r->search());
694
695 return usp->asReturnedValue();
696}
697
698ReturnedValue UrlCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv,
699 int argc, const Value *newTarget)
700{
701 ExecutionEngine *v4 = that->engine();
702
703 if (argc < 1 || argc > 2)
704 return v4->throwError(QLatin1String("Invalid amount of arguments"));
705
706 Scope scope(v4);
707
708 ScopedValue arg1(scope, argv[0]);
709
710 QString arg1String = arg1->toQString();
711 QString urlString;
712
713 if (argc == 2) {
714 ScopedValue arg2(scope, argv[1]);
715 String *arg2StringValue = arg2->stringValue();
716
717 if (arg2StringValue == nullptr)
718 return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
719
720 QUrl url = QUrl(arg2StringValue->toQString());
721 QUrl relativeUrl = QUrl(arg1String);
722
723 QString baseUrlPath = url.path();
724 QString relativePath = relativeUrl.path();
725
726 // If the base URL contains a path the last section of it is discarded
727 int lastSlash = baseUrlPath.lastIndexOf(QLatin1Char('/'));
728 if (lastSlash != -1)
729 baseUrlPath.truncate(lastSlash);
730
731 if (!relativePath.startsWith(QLatin1Char('/')))
732 relativePath = relativePath.prepend(QLatin1Char('/'));
733
734 url.setPath(baseUrlPath + relativePath);
735 url.setFragment(relativeUrl.fragment());
736 url.setQuery(relativeUrl.query());
737
738 urlString = url.toString();
739 } else {
740 urlString = arg1String;
741 }
742
743 ReturnedValue o = Encode(v4->newUrlObject());
744
745 if (!newTarget)
746 return o;
747
748 ScopedObject obj(scope, o);
749 obj->setProtoFromNewTarget(newTarget);
750
751 UrlObject *urlObject = obj->as<UrlObject>();
752
753 if (!urlObject->setHref(urlString))
754 return v4->throwTypeError(QLatin1String("Invalid URL: %1").arg(urlString));
755
756 return obj->asReturnedValue();
757}
758
759
760void Heap::UrlSearchParamsCtor::init(QV4::ExecutionEngine *engine)
761{
762 Heap::FunctionObject::init(engine, QLatin1String("URLSearchParams"));
763}
764
765void UrlSearchParamsPrototype::init(ExecutionEngine *engine, Object *ctor)
766{
767 Q_UNUSED(ctor);
768
769 Scope scope(engine);
770 ScopedObject o(scope);
771
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);
784}
785
786ReturnedValue UrlSearchParamsCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv,
787 int argc, const Value *newTarget)
788{
789 ExecutionEngine *v4 = that->engine();
790
791 if (argc > 1)
792 return v4->throwError(QLatin1String("Invalid amount of arguments"));
793
794 Scope scope(v4);
795
796 ScopedValue arg(scope, argv[0]);
797 ArrayObject *argArrayObject = arg->as<ArrayObject>();
798 Object *argObject = arg->as<Object>();
799
800 ReturnedValue o = Encode(v4->newUrlSearchParamsObject());
801
802 if (!newTarget)
803 return o;
804
805 ScopedObject obj(scope, o);
806 obj->setProtoFromNewTarget(newTarget);
807
808 UrlSearchParamsObject *urlSearchParamsObject = obj->as<UrlSearchParamsObject>();
809
810 if (argArrayObject != nullptr) {
811 ScopedArrayObject argArray(scope, argArrayObject);
812
813 uint len = argArray->getLength();
814
815 for (uint i = 0; i < len; i++) {
816 // safe to user fromReturnedValue: Normal array, which will ensure marking
817 QV4::Value pair = Value::fromReturnedValue(argArray->get(i));
818 auto *pairArrayObject = pair.as<ArrayObject>();
819
820 if (pairArrayObject == nullptr) {
821 return v4->throwTypeError(
822 QLatin1String("element %1 is not a pair").arg(QString::number(i)));
823 }
824
825
826 ScopedArrayObject pairArray(scope, pairArrayObject);
827
828
829 uint pairLen = pairArray->getLength();
830
831
832 if (pairLen != 2) {
833 return v4->throwTypeError(QLatin1String("pair %1 has %2 elements instead of 2")
834 .arg(QString::number(i))
835 .arg(QString::number(pairLen)));
836 }
837 }
838
839 urlSearchParamsObject->initializeParams(argArray);
840 } else if (argObject != nullptr) {
841 ScopedObject scopedObject(scope, argObject);
842 urlSearchParamsObject->initializeParams(scopedObject);
843 } else {
844 QString value = argc > 0 ? arg->toQString() : QLatin1String("");
845 urlSearchParamsObject->initializeParams(value);
846 }
847
848 return obj->asReturnedValue();
849}
850
851void UrlSearchParamsObject::initializeParams()
852{
853 auto *arrayObject = engine()->newArrayObject(0);
854 auto *keys = engine()->newArrayObject(0);
855 auto *values = engine()->newArrayObject(0);
856
857 d()->params.set(engine(), arrayObject);
858 d()->keys.set(engine(), keys);
859 d()->values.set(engine(), values);
860}
861
862void UrlSearchParamsObject::initializeParams(QString value)
863{
864 Q_ASSERT(d()->params == nullptr);
865
866 initializeParams();
867
868 if (value.startsWith(QLatin1Char('?')))
869 value = value.mid(1);
870
871 const QStringList params = value.split(QLatin1Char('&'));
872
873 for (const QString& param : params) {
874 if (param.isEmpty())
875 continue;
876
877 QString key, value;
878
879 int equalsIndex = param.indexOf(QLatin1Char('='));
880 if (equalsIndex != -1) {
881 key = param.left(equalsIndex);
882 value = param.mid(equalsIndex+1);
883 } else {
884 key = param;
885 }
886
887 append(engine()->newString(key), engine()->newString(value));
888 }
889}
890
891void UrlSearchParamsObject::initializeParams(ScopedArrayObject& params)
892{
893 Q_ASSERT(d()->params == nullptr);
894
895 Scope scope(engine());
896
897 uint len = params->getLength();
898 auto *keys = engine()->newArrayObject(len);
899 auto *values = engine()->newArrayObject(len);
900
901 ScopedArrayObject scopedKeys(scope, keys);
902 ScopedArrayObject scopedValues(scope, values);
903
904 for (uint i = 0; i < len; i++)
905 {
906 // fromReturnedValue is safe; everything is reachable via params
907 // so the gc won't collect it; we control params, so there can't be
908 // any weird proxy magic
909 QV4::Value pair = Value::fromReturnedValue(params->get(i));
910 auto *pairArrayObject = pair.as<ArrayObject>();
911
912 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
913 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(uint(1)));
914
915 scopedKeys->put(i, key);
916 scopedValues->put(i, value);
917 }
918
919
920 d()->params.set(engine(), params->d());
921 d()->keys.set(engine(), keys);
922 d()->values.set(engine(), values);
923}
924
925void UrlSearchParamsObject::initializeParams(ScopedObject& params)
926{
927 Q_ASSERT(d()->params == nullptr);
928
929 initializeParams();
930
931 Scope scope(engine());
932 ObjectIterator it(scope, params, ObjectIterator::EnumerableOnly);
933
934 ScopedValue name(scope);
935 ScopedValue val(scope);
936
937 while (true) {
938 name = it.nextPropertyNameAsString(val);
939 if (name->isNull())
940 break;
941
942 Heap::String *nameStr = name->as<String>()->d();
943 Heap::String *valStr = val->toString(engine());
944
945 append(nameStr, valStr);
946 }
947}
948
949void UrlSearchParamsObject::setParams(QList<QStringList> params)
950{
951 auto *arrayObject = engine()->newArrayObject(0);
952 auto *keys = engine()->newArrayObject(0);
953 auto *values = engine()->newArrayObject(0);
954
955 Scope scope(engine());
956
957 ScopedArrayObject scopedArray(scope, arrayObject);
958
959 ScopedArrayObject scopedKeys(scope, keys);
960 ScopedArrayObject scopedValues(scope, values);
961
962 uint len = 0;
963
964 for (const QStringList& param : params) {
965
966 auto *valuePair = engine()->newArrayObject(2);
967
968 ScopedArrayObject valuePairObject(scope, valuePair);
969
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);
974
975 scopedKeys->put(len, key);
976 scopedValues->put(len, value);
977
978 scopedArray->put(len, valuePairObject);
979 len++;
980 }
981
982 d()->params.set(engine(), arrayObject);
983 d()->keys.set(engine(), keys);
984 d()->values.set(engine(), values);
985}
986
987void UrlSearchParamsObject::setUrlObject(const UrlObject *url)
988{
989 d()->url.set(engine(), url->d());
990}
991
992void UrlSearchParamsObject::append(Heap::String *name, Heap::String *value)
993{
994 Scope scope(engine());
995
996 ScopedArrayObject scopedArray(scope, d()->params);
997 ScopedArrayObject scopedKeys(scope, d()->keys);
998 ScopedArrayObject scopedValues(scope, d()->values);
999
1000 auto *valuePair = engine()->newArrayObject(2);
1001
1002 ScopedArrayObject valuePairObject(scope, valuePair);
1003
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);
1008
1009 uint len = scopedArray->getLength();
1010
1011 scopedKeys->put(len, keyScoped);
1012 scopedValues->put(len, valueScoped);
1013
1014 scopedArray->put(len, valuePairObject);
1015}
1016
1017QList<QStringList> UrlSearchParamsObject::params() const
1018{
1019 auto *arrayObject = d()->params.get();
1020 Scope scope(engine());
1021 ScopedArrayObject scopedArray(scope, arrayObject);
1022
1023 QList<QStringList> result;
1024
1025 uint len = scopedArray->getLength();
1026
1027 for (uint i = 0; i < len; i++) {
1028 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(i));
1029 auto *pairArrayObject = pair.as<ArrayObject>();
1030
1031 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
1032 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(uint(1)));
1033
1034 result << QStringList { key.toQString(), value.toQString() };
1035 }
1036
1037 return result;
1038}
1039
1040Heap::UrlObject *UrlSearchParamsObject::urlObject() const
1041{
1042 return d()->url.get();
1043}
1044
1045QString UrlSearchParamsObject::searchString() const
1046{
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 &param = params[i];
1052 search += param[0] + QLatin1Char('=') + param[1];
1053 if (i != len - 1)
1054 search += QLatin1Char('&');
1055 }
1056 return search;
1057}
1058
1059int UrlSearchParamsObject::length() const
1060{
1061 auto *arrayObject = d()->params.get();
1062 Scope scope(engine());
1063 ScopedArrayObject scopedArray(scope, arrayObject);
1064
1065 return scopedArray->getLength();
1066}
1067
1068int UrlSearchParamsObject::indexOf(QString name, int last) const
1069{
1070 auto *arrayObject = d()->params.get();
1071 Scope scope(engine());
1072 ScopedArrayObject scopedArray(scope, arrayObject);
1073
1074 int len = scopedArray->getLength();
1075
1076 for (int i = last + 1; i < len; i++) {
1077 // fromReturnedValue is safe, scopedArray is a normal array and takes care of marking
1078 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(i));
1079 auto *pairArrayObject = pair.as<ArrayObject>();
1080
1081 QV4::Value key = Value::fromReturnedValue(pairArrayObject->get(uint(0)));
1082
1083 if (key.toQString() == name)
1084 return i;
1085 }
1086
1087 return -1;
1088}
1089
1090QString UrlSearchParamsObject::stringAt(int index, int pairIndex) const
1091{
1092 auto *arrayObject = d()->params.get();
1093 Scope scope(engine());
1094 ScopedArrayObject scopedArray(scope, arrayObject);
1095
1096 if (index >= scopedArray->getLength())
1097 return {};
1098
1099 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(index));
1100 auto *pairArrayObject = pair.as<ArrayObject>();
1101
1102 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(pairIndex));
1103
1104 return value.toQString();
1105}
1106
1107QV4::Heap::String * UrlSearchParamsObject::stringAtRaw(int index, int pairIndex) const
1108{
1109 auto *arrayObject = d()->params.get();
1110 Scope scope(engine());
1111 ScopedArrayObject scopedArray(scope, arrayObject);
1112
1113 if (index >= scopedArray->getLength())
1114 return nullptr;
1115
1116 QV4::Value pair = Value::fromReturnedValue(scopedArray->get(index));
1117 auto *pairArrayObject = pair.as<ArrayObject>();
1118
1119 QV4::Value value = Value::fromReturnedValue(pairArrayObject->get(pairIndex));
1120
1121 return value.as<String>()->d();
1122}
1123
1124QString UrlSearchParamsObject::nameAt(int index) const
1125{
1126 return stringAt(index, 0);
1127}
1128
1129QV4::Heap::String * UrlSearchParamsObject::nameAtRaw(int index) const
1130{
1131 return stringAtRaw(index, 0);
1132}
1133
1134
1135QString UrlSearchParamsObject::valueAt(int index) const
1136{
1137 return stringAt(index, 1);
1138}
1139
1140QV4::Heap::String * UrlSearchParamsObject::valueAtRaw(int index) const
1141{
1142 return stringAtRaw(index, 1);
1143}
1144
1145namespace {
1146struct UrlSearchParamsObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
1147{
1148 ~UrlSearchParamsObjectOwnPropertyKeyIterator() override = default;
1149 PropertyKey next(const QV4::Object *o, Property *pd = nullptr,
1150 PropertyAttributes *attrs = nullptr) override;
1151};
1152} // namespace
1153
1154PropertyKey UrlSearchParamsObjectOwnPropertyKeyIterator::next(const QV4::Object *o, Property *pd,
1155 PropertyAttributes *attrs)
1156{
1157 const UrlSearchParamsObject *usp = static_cast<const UrlSearchParamsObject *>(o);
1158
1159 Scope scope(usp);
1160
1161 uint len = usp->length();
1162 if (arrayIndex < len) {
1163 uint index = arrayIndex;
1164 ++arrayIndex;
1165 if (attrs)
1166 *attrs = Attr_NotConfigurable | Attr_NotWritable;
1167 if (pd)
1168 pd->value = usp->engine()->newString(usp->nameAt(index));
1169 return PropertyKey::fromArrayIndex(index);
1170 }
1171
1172 return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
1173}
1174
1175OwnPropertyKeyIterator *UrlSearchParamsObject::virtualOwnPropertyKeys(const Object *m,
1176 Value *target)
1177{
1178 *target = *m;
1179 return new UrlSearchParamsObjectOwnPropertyKeyIterator;
1180}
1181
1182PropertyAttributes UrlSearchParamsObject::virtualGetOwnProperty(const Managed *m, PropertyKey id,
1183 Property *p)
1184{
1185 PropertyAttributes attributes = Object::virtualGetOwnProperty(m, id, p);
1186 if (attributes != Attr_Invalid)
1187 return attributes;
1188
1189 if (id.isArrayIndex()) {
1190 const int index = id.asArrayIndex();
1191 const auto usp = static_cast<const UrlSearchParamsObject *>(m);
1192 if (index < usp->length()) {
1193 if (p)
1194 p->value = usp->engine()->newString(usp->nameAt(index));
1195 return Attr_NotConfigurable | Attr_NotWritable;
1196 }
1197 }
1198
1199 return Object::virtualGetOwnProperty(m, id, p);
1200}
1201
1202static bool checkSearchParamsType(ExecutionEngine *v4, const Scoped<UrlSearchParamsObject> &o)
1203{
1204 if (o)
1205 return true;
1206
1207 v4->throwTypeError(QStringLiteral("Value of \"this\" must be of type URLSearchParams"));
1208 return false;
1209}
1210
1211ReturnedValue UrlSearchParamsPrototype::method_toString(
1212 const FunctionObject *b, const Value *thisObject, const Value *, int)
1213{
1214 ExecutionEngine *v4 = b->engine();
1215 Scope scope(v4);
1216
1217 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1218 if (!checkSearchParamsType(v4, o))
1219 return Encode::undefined();
1220
1221 auto params = o->params();
1222
1223 QString value;
1224
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])));
1228
1229 value.chop(1);
1230
1231 return Encode(v4->newString(value));
1232}
1233
1234ReturnedValue UrlSearchParamsPrototype::method_sort(const FunctionObject *b, const Value *thisObject,
1235 const Value *, int)
1236{
1237 ExecutionEngine *v4 = b->engine();
1238 Scope scope(v4);
1239
1240 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1241 if (!checkSearchParamsType(v4, o))
1242 return Encode::undefined();
1243
1244 QList<QStringList> params = o->params();
1245 std::stable_sort(params.begin(), params.end(), [](QStringList a, QStringList b) { return a[0] < b[0]; });
1246
1247 o->setParams(params);
1248
1249 return Encode::undefined();
1250}
1251
1252ReturnedValue UrlSearchParamsPrototype::method_append(const FunctionObject *b, const Value *thisObject,
1253 const Value *argv, int argc)
1254{
1255 ExecutionEngine *v4 = b->engine();
1256 Scope scope(v4);
1257
1258 if (argc != 2)
1259 return v4->throwError(QLatin1String("Bad amount of arguments"));
1260
1261 ScopedValue argName(scope, argv[0]);
1262 ScopedValue argValue(scope, argv[1]);
1263
1264 String *argNameString = argName->stringValue();
1265
1266 if (argNameString == nullptr)
1267 return v4->throwTypeError(QLatin1String("Invalid argument provided"));
1268
1269 ScopedString name(scope, argName->as<String>());
1270 ScopedString value(scope, argValue->toString(v4));
1271
1272 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1273 if (!checkSearchParamsType(v4, o))
1274 return Encode::undefined();
1275
1276 o->append(name->d(), value->d());
1277
1278 return Encode::undefined();
1279}
1280
1281ReturnedValue UrlSearchParamsPrototype::method_delete(const FunctionObject *b, const Value *thisObject,
1282 const Value *argv, int argc)
1283{
1284 ExecutionEngine *v4 = b->engine();
1285 Scope scope(v4);
1286
1287 if (argc != 1)
1288 return v4->throwError(QLatin1String("Bad amount of arguments"));
1289
1290 ScopedValue argName(scope, argv[0]);
1291
1292 String *argNameString = argName->stringValue();
1293
1294 if (argNameString == nullptr)
1295 return v4->throwTypeError(QLatin1String("Invalid argument provided"));
1296
1297 QString name = argNameString->toQString();
1298
1299 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1300 if (!checkSearchParamsType(v4, o))
1301 return Encode::undefined();
1302
1303 QList<QStringList> params = o->params();
1304 params.removeIf([&name](const auto &pair) { return pair.at(0) == name; });
1305
1306 o->setParams(params);
1307
1308 return Encode::undefined();
1309}
1310
1311ReturnedValue UrlSearchParamsPrototype::method_has(const FunctionObject *b, const Value *thisObject,
1312 const Value *argv, int argc)
1313{
1314 ExecutionEngine *v4 = b->engine();
1315 Scope scope(v4);
1316
1317 if (argc != 1)
1318 return v4->throwError(QLatin1String("Bad amount of arguments"));
1319
1320 ScopedValue argName(scope, argv[0]);
1321
1322 String *argNameString = argName->stringValue();
1323
1324 if (argNameString == nullptr)
1325 return v4->throwTypeError(QLatin1String("Invalid argument provided"));
1326
1327 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1328 if (!checkSearchParamsType(v4, o))
1329 return Encode::undefined();
1330
1331 QString name = argNameString->toQString();
1332
1333 return Encode(o->indexOf(name) != -1);
1334}
1335
1336ReturnedValue UrlSearchParamsPrototype::method_set(const FunctionObject *b, const Value *thisObject,
1337 const Value *argv, int argc)
1338{
1339 ExecutionEngine *v4 = b->engine();
1340 Scope scope(v4);
1341
1342 if (argc != 2)
1343 return v4->throwError(QLatin1String("Bad amount of arguments"));
1344
1345 ScopedValue argName(scope, argv[0]);
1346 ScopedValue argValue(scope, argv[1]);
1347
1348 String *argNameString = argName->stringValue();
1349
1350 if (argNameString == nullptr)
1351 return v4->throwTypeError(QLatin1String("Invalid argument provided"));
1352
1353 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1354 if (!checkSearchParamsType(v4, o))
1355 return Encode::undefined();
1356
1357 QString name = argNameString->toQString();
1358 QString value = argValue->toQString();
1359
1360 auto params = o->params();
1361
1362 bool matched = false;
1363
1364 for (auto it = params.begin(); it != params.end();) {
1365 QStringList &param = *it;
1366 if (param[0] == name) {
1367 if (!matched) {
1368 param[1] = value;
1369 matched = true;
1370 } else {
1371 it = params.erase(it);
1372 continue;
1373 }
1374 }
1375 it++;
1376 }
1377
1378 if (!matched)
1379 params << QStringList { name, value };
1380
1381 o->setParams(params);
1382
1383 Scoped<UrlObject> scopedUrlObject(scope, o->d()->url.get());
1384 if (scopedUrlObject)
1385 scopedUrlObject->setSearch(o->searchString());
1386
1387 return Encode::undefined();
1388}
1389
1390ReturnedValue UrlSearchParamsPrototype::method_get(const FunctionObject *b, const Value *thisObject,
1391 const Value *argv, int argc)
1392{
1393 ExecutionEngine *v4 = b->engine();
1394 Scope scope(v4);
1395
1396 if (argc != 1)
1397 return v4->throwError(QLatin1String("Bad amount of arguments"));
1398
1399 ScopedValue argName(scope, argv[0]);
1400
1401 String *argNameString = argName->stringValue();
1402
1403 if (argNameString == nullptr)
1404 return v4->throwTypeError(QLatin1String("Invalid argument provided"));
1405
1406 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1407 if (!checkSearchParamsType(v4, o))
1408 return Encode::undefined();
1409
1410 QString name = argNameString->toQString();
1411
1412 int index = o->indexOf(name);
1413
1414 if (index == -1)
1415 return Encode::null();
1416
1417 return Encode(o->valueAtRaw(index));
1418}
1419
1420ReturnedValue UrlSearchParamsPrototype::method_getAll(const FunctionObject *b,
1421 const Value *thisObject, const Value *argv,
1422 int argc)
1423{
1424 ExecutionEngine *v4 = b->engine();
1425 Scope scope(v4);
1426
1427 if (argc != 1)
1428 return v4->throwError(QLatin1String("Bad amount of arguments"));
1429
1430 ScopedValue argName(scope, argv[0]);
1431
1432 String *argNameString = argName->stringValue();
1433
1434 if (argNameString == nullptr)
1435 return v4->throwTypeError(QLatin1String("Invalid argument provided"));
1436
1437 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1438 if (!checkSearchParamsType(v4, o))
1439 return Encode::undefined();
1440
1441 QString name = argNameString->toQString();
1442
1443 auto *arrayObject = v4->newArrayObject(0);
1444 ScopedArrayObject result(scope, arrayObject);
1445
1446 int i = 0;
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);
1450 }
1451
1452 return Encode(arrayObject);
1453}
1454
1455ReturnedValue UrlSearchParamsPrototype::method_forEach(const FunctionObject *b,
1456 const Value *thisObject, const Value *argv,
1457 int argc)
1458{
1459 ExecutionEngine *v4 = b->engine();
1460 Scope scope(v4);
1461
1462 if (argc != 1)
1463 return v4->throwError(QLatin1String("Bad amount of arguments"));
1464
1465 ScopedValue argFunc(scope, argv[0]);
1466
1467 FunctionObject *func = argFunc->as<FunctionObject>();
1468
1469 if (func == nullptr)
1470 return v4->throwTypeError(QLatin1String("Invalid argument: must be a function"));
1471
1472 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1473 if (!checkSearchParamsType(v4, o))
1474 return Encode::undefined();
1475
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));
1479
1480 QV4::JSCallArguments calldata(scope, 2);
1481
1482 calldata.args[0] = value;
1483 calldata.args[1] = name;
1484
1485 func->call(calldata);
1486 }
1487
1488 return Encode::undefined();
1489}
1490
1491ReturnedValue UrlSearchParamsPrototype::method_entries(const FunctionObject *b,
1492 const Value *thisObject, const Value *,
1493 int argc)
1494{
1495 ExecutionEngine *v4 = b->engine();
1496 Scope scope(v4);
1497
1498 if (argc != 0)
1499 return v4->throwError(QLatin1String("Bad amount of arguments"));
1500
1501 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1502 if (!checkSearchParamsType(v4, o))
1503 return Encode::undefined();
1504
1505 ScopedObject params(scope, o->d()->params.get());
1506
1507 Scoped<ArrayIteratorObject> paramsIterator(scope, v4->newArrayIteratorObject(params));
1508 paramsIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1509 return paramsIterator->asReturnedValue();
1510}
1511
1512ReturnedValue UrlSearchParamsPrototype::method_keys(const FunctionObject *b,
1513 const Value *thisObject, const Value *,
1514 int argc)
1515{
1516 ExecutionEngine *v4 = b->engine();
1517 Scope scope(v4);
1518
1519 if (argc != 0)
1520 return v4->throwError(QLatin1String("Bad amount of arguments"));
1521
1522 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1523 if (!checkSearchParamsType(v4, o))
1524 return Encode::undefined();
1525
1526 ScopedObject keys(scope, o->d()->keys.get());
1527
1528 Scoped<ArrayIteratorObject> keysIterator(scope, v4->newArrayIteratorObject(keys));
1529 keysIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1530 return keysIterator->asReturnedValue();
1531}
1532
1533ReturnedValue UrlSearchParamsPrototype::method_values(const FunctionObject *b,
1534 const Value *thisObject, const Value *,
1535 int argc)
1536{
1537 ExecutionEngine *v4 = b->engine();
1538 Scope scope(v4);
1539
1540 if (argc != 0)
1541 return v4->throwError(QLatin1String("Bad amount of arguments"));
1542
1543 Scoped<UrlSearchParamsObject> o(scope, thisObject);
1544 if (!checkSearchParamsType(v4, o))
1545 return Encode::undefined();
1546
1547 ScopedObject values(scope, o->d()->values.get());
1548
1549 Scoped<ArrayIteratorObject> valuesIterator(scope, v4->newArrayIteratorObject(values));
1550 valuesIterator->d()->iterationKind = IteratorKind::KeyValueIteratorKind;
1551 return valuesIterator->asReturnedValue();
1552}
Definition qjsvalue.h:23
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)