(init = undefined)
| 335 | // Default parameter is necessary to keep URLSearchParams.length === 0 in |
| 336 | // accordance with Web IDL spec. |
| 337 | constructor(init = undefined) { |
| 338 | markTransferMode(this, false, false); |
| 339 | |
| 340 | if (init === undefined) { |
| 341 | // Do nothing |
| 342 | } else if (init !== null && (typeof init === 'object' || typeof init === 'function')) { |
| 343 | const method = init[SymbolIterator]; |
| 344 | if (method === this[SymbolIterator] && #searchParams in init) { |
| 345 | // While the spec does not have this branch, we can use it as a |
| 346 | // shortcut to avoid having to go through the costly generic iterator. |
| 347 | const childParams = init.#searchParams; |
| 348 | this.#searchParams = childParams.slice(); |
| 349 | } else if (method != null) { |
| 350 | // Sequence<sequence<USVString>> |
| 351 | if (typeof method !== 'function') { |
| 352 | throw new ERR_ARG_NOT_ITERABLE('Query pairs'); |
| 353 | } |
| 354 | |
| 355 | // The following implementation differs from the URL specification: |
| 356 | // Sequences must first be converted from ECMAScript objects before |
| 357 | // and operations are done on them, and the operation of converting |
| 358 | // the sequences would first exhaust the iterators. If the iterator |
| 359 | // returns something invalid in the middle, whether it would be called |
| 360 | // after that would be an observable change to the users. |
| 361 | // Exhausting the iterator and later converting them to USVString comes |
| 362 | // with a significant cost (~40-80%). In order optimize URLSearchParams |
| 363 | // creation duration, Node.js merges the iteration and converting |
| 364 | // iterations into a single iteration. |
| 365 | for (const pair of init) { |
| 366 | if (pair == null) { |
| 367 | throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); |
| 368 | } else if (ArrayIsArray(pair)) { |
| 369 | // If innerSequence's size is not 2, then throw a TypeError. |
| 370 | if (pair.length !== 2) { |
| 371 | throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); |
| 372 | } |
| 373 | // Append (innerSequence[0], innerSequence[1]) to query's list. |
| 374 | ArrayPrototypePush( |
| 375 | this.#searchParams, |
| 376 | StringPrototypeToWellFormed(`${pair[0]}`), |
| 377 | StringPrototypeToWellFormed(`${pair[1]}`), |
| 378 | ); |
| 379 | } else { |
| 380 | if (((typeof pair !== 'object' && typeof pair !== 'function') || |
| 381 | typeof pair[SymbolIterator] !== 'function')) { |
| 382 | throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); |
| 383 | } |
| 384 | |
| 385 | let length = 0; |
| 386 | |
| 387 | for (const element of pair) { |
| 388 | length++; |
| 389 | ArrayPrototypePush(this.#searchParams, StringPrototypeToWellFormed(`${element}`)); |
| 390 | } |
| 391 | |
| 392 | // If innerSequence's size is not 2, then throw a TypeError. |
| 393 | if (length !== 2) { |
| 394 | throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); |
nothing calls this directly
no test coverage detected