GeezerVison is showing github.com — url: add value argument to has and delete methods · nodejs/node@a0634d7
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: benchmark/common.js +3-2Lines changed: 3 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -360,8 +360,9 @@ function getUrlData(withBase) { | 360 | 360 | for (const item of data) { | 361 | 361 | if (item.failure || !item.input) continue; | 362 | 362 | if (withBase) { | 363 | | - result.push([item.input, item.base]); | 364 | | - } else if (item.base !== 'about:blank') { | | 363 | + // item.base might be null. It should be converted into `undefined`. | | 364 | + result.push([item.input, item.base ?? undefined]); | | 365 | + } else if (item.base !== null) { | 365 | 366 | result.push(item.base); | 366 | 367 | } | 367 | 368 | } | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/url.md +30-4Lines changed: 30 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -859,11 +859,22 @@ new URLSearchParams([ | 859 | 859 |
| 860 | 860 | Append a new name-value pair to the query string. | 861 | 861 |
| 862 | | -#### `urlSearchParams.delete(name)` | | 862 | +#### `urlSearchParams.delete(name[, value])` | | 863 | + | | 864 | +<!-- YAML | | 865 | +changes: | | 866 | + - version: REPLACEME | | 867 | + pr-url: https://github.com/nodejs/node/pull/47885 | | 868 | + description: Add support for optional `value` argument. | | 869 | +--> | 863 | 870 |
| 864 | 871 | * `name` {string} | | 872 | +* `value` {string} | | 873 | + | | 874 | +If `value` is provided, removes all name-value pairs | | 875 | +where name is `name` and value is `value`.. | 865 | 876 |
| 866 | | -Remove all name-value pairs whose name is `name`. | | 877 | +If `value` is not provided, removes all name-value pairs whose name is `name`. | 867 | 878 |
| 868 | 879 | #### `urlSearchParams.entries()` | 869 | 880 |
| @@ -918,12 +929,27 @@ are no such pairs, `null` is returned. | 918 | 929 | Returns the values of all name-value pairs whose name is `name`. If there are | 919 | 930 | no such pairs, an empty array is returned. | 920 | 931 |
| 921 | | -#### `urlSearchParams.has(name)` | | 932 | +#### `urlSearchParams.has(name[, value])` | | 933 | + | | 934 | +<!-- YAML | | 935 | +changes: | | 936 | + - version: REPLACEME | | 937 | + pr-url: https://github.com/nodejs/node/pull/47885 | | 938 | + description: Add support for optional `value` argument. | | 939 | +--> | 922 | 940 |
| 923 | 941 | * `name` {string} | | 942 | +* `value` {string} | 924 | 943 | * Returns: {boolean} | 925 | 944 |
| 926 | | -Returns `true` if there is at least one name-value pair whose name is `name`. | | 945 | +Checks if the `URLSearchParams` object contains key-value pair(s) based on | | 946 | +`name` and an optional `value` argument. | | 947 | + | | 948 | +If `value` is provided, returns `true` when name-value pair with | | 949 | +same `name` and `value` exists. | | 950 | + | | 951 | +If `value` is not provided, returns `true` if there is at least one name-value | | 952 | +pair whose name is `name`. | 927 | 953 |
| 928 | 954 | #### `urlSearchParams.keys()` | 929 | 955 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/url.js +28-9Lines changed: 28 additions & 9 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -435,7 +435,7 @@ class URLSearchParams { | 435 | 435 | } | 436 | 436 | } | 437 | 437 |
| 438 | | - delete(name) { | | 438 | + delete(name, value = undefined) { | 439 | 439 | if (typeof this !== 'object' || this === null || !(#searchParams in this)) | 440 | 440 | throw new ERR_INVALID_THIS('URLSearchParams'); | 441 | 441 |
| @@ -445,12 +445,23 @@ class URLSearchParams { | 445 | 445 |
| 446 | 446 | const list = this.#searchParams; | 447 | 447 | name = toUSVString(name); | 448 | | - for (let i = 0; i < list.length;) { | 449 | | - const cur = list[i]; | 450 | | - if (cur === name) { | 451 | | - list.splice(i, 2); | 452 | | - } else { | 453 | | - i += 2; | | 448 | + | | 449 | + if (value !== undefined) { | | 450 | + value = toUSVString(value); | | 451 | + for (let i = 0; i < list.length;) { | | 452 | + if (list[i] === name && list[i + 1] === value) { | | 453 | + list.splice(i, 2); | | 454 | + } else { | | 455 | + i += 2; | | 456 | + } | | 457 | + } | | 458 | + } else { | | 459 | + for (let i = 0; i < list.length;) { | | 460 | + if (list[i] === name) { | | 461 | + list.splice(i, 2); | | 462 | + } else { | | 463 | + i += 2; | | 464 | + } | 454 | 465 | } | 455 | 466 | } | 456 | 467 | if (this.#context) { | @@ -495,7 +506,7 @@ class URLSearchParams { | 495 | 506 | return values; | 496 | 507 | } | 497 | 508 |
| 498 | | - has(name) { | | 509 | + has(name, value = undefined) { | 499 | 510 | if (typeof this !== 'object' || this === null || !(#searchParams in this)) | 500 | 511 | throw new ERR_INVALID_THIS('URLSearchParams'); | 501 | 512 |
| @@ -505,11 +516,19 @@ class URLSearchParams { | 505 | 516 |
| 506 | 517 | const list = this.#searchParams; | 507 | 518 | name = toUSVString(name); | | 519 | + | | 520 | + if (value !== undefined) { | | 521 | + value = toUSVString(value); | | 522 | + } | | 523 | + | 508 | 524 | for (let i = 0; i < list.length; i += 2) { | 509 | 525 | if (list[i] === name) { | 510 | | - return true; | | 526 | + if (value === undefined || list[i + 1] === value) { | | 527 | + return true; | | 528 | + } | 511 | 529 | } | 512 | 530 | } | | 531 | + | 513 | 532 | return false; | 514 | 533 | } | 515 | 534 |
| |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/wpt/README.md +1-1Lines changed: 1 addition & 1 deletion - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -27,7 +27,7 @@ Last update: | 27 | 27 | - resource-timing: https://github.com/web-platform-tests/wpt/tree/22d38586d0/resource-timing | 28 | 28 | - resources: https://github.com/web-platform-tests/wpt/tree/919874f84f/resources | 29 | 29 | - streams: https://github.com/web-platform-tests/wpt/tree/51750bc8d7/streams | 30 | | -- url: https://github.com/web-platform-tests/wpt/tree/7c5c3cc125/url | | 30 | +- url: https://github.com/web-platform-tests/wpt/tree/c4726447f3/url | 31 | 31 | - user-timing: https://github.com/web-platform-tests/wpt/tree/df24fb604e/user-timing | 32 | 32 | - wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi | 33 | 33 | - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi | |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/wpt/url/README.md +24-26Lines changed: 24 additions & 26 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | ## urltestdata.json | 2 | 2 |
| 3 | | -These tests are for browsers, but the data for | 4 | | -`a-element.html`, `url-constructor.html`, `a-element-xhtml.xhtml`, and `failure.html` | 5 | | -is in `resources/urltestdata.json` and can be re-used by non-browser implementations. | 6 | | -This file contains a JSON array of comments as strings and test cases as objects. | 7 | | -The keys for each test case are: | 8 | | - | 9 | | -* `base`: an absolute URL as a string whose [parsing] without a base of its own must succeed. | 10 | | - This key is always present, | 11 | | - and may have a value like `"about:blank"` when `input` is an absolute URL. | 12 | | -* `input`: an URL as a string to be [parsed][parsing] with `base` as its base URL. | 13 | | -* Either: | 14 | | - * `failure` with the value `true`, indicating that parsing `input` should return failure, | 15 | | - * or `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`, | 16 | | - `pathname`, `search`, and `hash` with string values; | 17 | | - indicating that parsing `input` should return an URL record | 18 | | - and that the getters of each corresponding attribute in that URL’s [API] | 19 | | - should return the corresponding value. | 20 | | - | 21 | | - The `origin` key may be missing. | 22 | | - In that case, the API’s `origin` attribute is not tested. | 23 | | - | 24 | | -In addition to testing that parsing `input` against `base` gives the result, a test harness for the | 25 | | -`URL` constructor (or similar APIs) should additionally test the following pattern: if `failure` is | 26 | | -true, parsing `about:blank` against `input` must give failure. This tests that the logic for | 27 | | -converting base URLs into strings properly fails the whole parsing algorithm if the base URL cannot | 28 | | -be parsed. | | 3 | +`resources/urltestdata.json` contains URL parsing tests suitable for any URL parser implementation. | | 4 | + | | 5 | +It's used as a source of tests by `a-element.html`, `failure.html`, `url-constructor.any.js`, and | | 6 | +other test files in this directory. | | 7 | + | | 8 | +The format of `resources/urltestdata.json` is a JSON array of comments as strings and test cases as | | 9 | +objects. The keys for each test case are: | | 10 | + | | 11 | +* `input`: a string to be parsed as URL. | | 12 | +* `base`: null or a serialized URL (i.e., does not fail parsing). | | 13 | +* Then either | | 14 | + | | 15 | + * `failure` whose value is `true`, indicating that parsing `input` relative to `base` returns | | 16 | + failure | | 17 | + * `relativeTo` whose value is "`non-opaque-path-base`" (input does parse against a non-null base | | 18 | + URL without an opaque path) or "`any-base`" (input parses against any non-null base URL), or is | | 19 | + omitted in its entirety (input never parses successfully) | | 20 | + | | 21 | + or `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`, | | 22 | + `pathname`, `search`, and `hash` with string values; indicating that parsing `input` should return | | 23 | + an URL record and that the getters of each corresponding attribute in that URL’s [API] should | | 24 | + return the corresponding value. | | 25 | + | | 26 | + The `origin` key may be missing. In that case, the API’s `origin` attribute is not tested. | 29 | 27 |
| 30 | 28 | ## setters_tests.json | 31 | 29 |
| |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/wpt/url/failure.html +6-5Lines changed: 6 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 9 | 9 | promise_test(() => fetch("resources/urltestdata.json").then(res => res.json()).then(runTests), "Loading data…") | 10 | 10 |
| 11 | 11 | function runTests(testData) { | 12 | | - for(const test of testData) { | 13 | | - if (typeof test === "string" || !test.failure || test.base !== "about:blank") { | 14 | | - continue | | 12 | + for (const test of testData) { | | 13 | + if (typeof test === "string" || !test.failure || test.base !== null) { | | 14 | + continue; | 15 | 15 | } | 16 | 16 |
| 17 | 17 | const name = test.input + " should throw" | 18 | 18 |
| 19 | | - self.test(() => { // URL's constructor's first argument is tested by url-constructor.html | | 19 | + self.test(() => { | | 20 | + // URL's constructor's first argument is tested by url-constructor.html | 20 | 21 | // If a URL fails to parse with any valid base, it must also fail to parse with no base, i.e. | 21 | 22 | // when used as a base URL itself. | 22 | 23 | assert_throws_js(TypeError, () => new URL("about:blank", test.input)); | | 30 | 31 | // The following use cases resolve the URL input relative to the current | 31 | 32 | // document's URL. If this test input could be construed as a valid URL | 32 | 33 | // when resolved against a base URL, skip these cases. | 33 | | - if (!test.inputCanBeRelative) { | | 34 | + if (test.relativeTo === undefined) { | 34 | 35 | self.test(() => { | 35 | 36 | const client = new XMLHttpRequest() | 36 | 37 | assert_throws_dom("SyntaxError", () => client.open("GET", test.input)) | |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/wpt/url/historical.any.js +7Lines changed: 7 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -36,4 +36,11 @@ test(() => { | 36 | 36 | assert_throws_dom("DataCloneError", () => self.structuredClone(new URLSearchParams())); | 37 | 37 | }, "URLSearchParams: no structured serialize/deserialize support"); | 38 | 38 |
| | 39 | +test(() => { | | 40 | + const url = new URL("about:blank"); | | 41 | + url.toString = () => { throw 1 }; | | 42 | + assert_throws_exactly(1, () => new URL(url), "url argument"); | | 43 | + assert_throws_exactly(1, () => new URL("about:blank", url), "base argument"); | | 44 | +}, "Constructor only takes strings"); | | 45 | + | 39 | 46 | done(); |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/wpt/url/resources/a-element-origin.js +18-13Lines changed: 18 additions & 13 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -5,23 +5,28 @@ function setBase(base) { | 5 | 5 | } | 6 | 6 |
| 7 | 7 | function bURL(url, base) { | 8 | | - base = base || "about:blank" | 9 | | - setBase(base) | 10 | | - var a = document.createElement("a") | 11 | | - a.setAttribute("href", url) | 12 | | - return a | | 8 | + setBase(base); | | 9 | + const a = document.createElement("a"); | | 10 | + a.setAttribute("href", url); | | 11 | + return a; | 13 | 12 | } | 14 | 13 |
| 15 | | -function runURLTests(urltests) { | 16 | | - for(var i = 0, l = urltests.length; i < l; i++) { | 17 | | - var expected = urltests[i] | 18 | | - if (typeof expected === "string" || !("origin" in expected)) continue | 19 | | - // skip without base because you cannot unset the baseURL of a document | 20 | | - if (expected.base === null) continue; | | 14 | +function runURLTests(urlTests) { | | 15 | + for (const expected of urlTests) { | | 16 | + // Skip comments and tests without "origin" expectation | | 17 | + if (typeof expected === "string" || !("origin" in expected)) | | 18 | + continue; | | 19 | + | | 20 | + // Fragments are relative against "about:blank" (this might always be redundant due to requiring "origin" in expected) | | 21 | + if (expected.base === null && expected.input.startsWith("#")) | | 22 | + continue; | | 23 | + | | 24 | + // We cannot use a null base for HTML tests | | 25 | + const base = expected.base === null ? "about:blank" : expected.base; | 21 | 26 |
| 22 | 27 | test(function() { | 23 | | - var url = bURL(expected.input, expected.base) | | 28 | + var url = bURL(expected.input, base) | 24 | 29 | assert_equals(url.origin, expected.origin, "origin") | 25 | | - }, "Parsing origin: <" + expected.input + "> against <" + expected.base + ">") | | 30 | + }, "Parsing origin: <" + expected.input + "> against <" + base + ">") | 26 | 31 | } | 27 | 32 | } |
Collapse file Copy file name to clipboardExpand all lines: test/fixtures/wpt/url/resources/a-element.js +19-14Lines changed: 19 additions & 14 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | promise_test(() => fetch("resources/urltestdata.json").then(res => res.json()).then(runURLTests), "Loading data…"); | 2 | 2 |
| 3 | 3 | function setBase(base) { | 4 | | - document.getElementById("base").href = base | | 4 | + document.getElementById("base").href = base; | 5 | 5 | } | 6 | 6 |
| 7 | 7 | function bURL(url, base) { | 8 | | - base = base || "about:blank" | 9 | | - setBase(base) | 10 | | - var a = document.createElement("a") | 11 | | - a.setAttribute("href", url) | 12 | | - return a | | 8 | + setBase(base); | | 9 | + const a = document.createElement("a"); | | 10 | + a.setAttribute("href", url); | | 11 | + return a; | 13 | 12 | } | 14 | 13 |
| 15 | | -function runURLTests(urltests) { | 16 | | - for(var i = 0, l = urltests.length; i < l; i++) { | 17 | | - var expected = urltests[i] | 18 | | - if (typeof expected === "string") continue // skip comments | 19 | | - // skip without base because you cannot unset the baseURL of a document | 20 | | - if (expected.base === null) continue; | | 14 | +function runURLTests(urlTests) { | | 15 | + for (const expected of urlTests) { | | 16 | + // Skip comments | | 17 | + if (typeof expected === "string") | | 18 | + continue; | | 19 | + | | 20 | + // Fragments are relative against "about:blank" | | 21 | + if (expected.relativeTo === "any-base") | | 22 | + continue; | | 23 | + | | 24 | + // We cannot use a null base for HTML tests | | 25 | + const base = expected.base === null ? "about:blank" : expected.base; | 21 | 26 |
| 22 | 27 | function getKey(expected) { | 23 | 28 | if (expected.protocol) { | @@ -30,7 +35,7 @@ function runURLTests(urltests) { | 30 | 35 | } | 31 | 36 |
| 32 | 37 | subsetTestByKey(getKey(expected), test, function() { | 33 | | - var url = bURL(expected.input, expected.base) | | 38 | + var url = bURL(expected.input, base) | 34 | 39 | if(expected.failure) { | 35 | 40 | if(url.protocol !== ':') { | 36 | 41 | assert_unreached("Expected URL to fail parsing") | @@ -49,6 +54,6 @@ function runURLTests(urltests) { | 49 | 54 | assert_equals(url.pathname, expected.pathname, "pathname") | 50 | 55 | assert_equals(url.search, expected.search, "search") | 51 | 56 | assert_equals(url.hash, expected.hash, "hash") | 52 | | - }, "Parsing: <" + expected.input + "> against <" + expected.base + ">") | | 57 | + }, "Parsing: <" + expected.input + "> against <" + base + ">") | 53 | 58 | } | 54 | 59 | } |
|