Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add value argument of URLSearchParams.prototype.{ has, delete } #1257

Merged
merged 3 commits into from
Jun 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- The methods renamed to end with `Symbol`, [May 2023 TC39 meeting](https://github.com/tc39/notes/blob/main/meetings/2023-05/may-15.md#symbol-predicates):
- `Symbol.isRegistered` -> `Symbol.isRegisteredSymbol` method
- `Symbol.isWellKnown` -> `Symbol.isWellKnownSymbol` method
- Added `value` argument of `URLSearchParams.prototype.{ has, delete }`, [url/735](https://github.com/whatwg/url/pull/735)
- Fixed some cases of increasing buffer size in `ArrayBuffer.prototype.{ transfer, transferToFixedLength }` polyfills
- Fixed awaiting async `AsyncDisposableStack.prototype.adopt` callback, [#1258](https://github.com/zloirock/core-js/issues/1258)
- Added TypeScript definitions to `core-js-compat`, [#1235](https://github.com/zloirock/core-js/issues/1235), thanks [@susnux](https://github.com/susnux)
Expand All @@ -33,6 +34,7 @@
- Methods from the [change `Array` by copy proposal](https://github.com/tc39/proposal-change-array-by-copy) marked as supported from FF115
- [`Array.fromAsync`](https://github.com/tc39/proposal-array-from-async) marked as supported from FF115
- [`URL.canParse`](https://url.spec.whatwg.org/#dom-url-canparse) marked as supported from FF115
- `value` argument of `URLSearchParams.prototype.{ has, delete }` marked as supported from [NodeJS 20.2.0](https://github.com/nodejs/node/pull/47885) and FF115
- Added Deno 1.34 compat data mapping
- Added Electron 26 compat data mapping
- Added Samsung Internet 22 compat data mapping
Expand Down
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3239,7 +3239,7 @@ queueMicrotask(() => console.log('called as microtask'));
```

#### `URL` and `URLSearchParams`[⬆](#index)
[`URL` standard](https://url.spec.whatwg.org/) implementation. Modules [`web.url`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url.js), [`web.url.can-parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url.can-parse.js), [`web.url.to-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url.to-json.js), [`web.url-search-params`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url-search-params.js), [`web.url-search-params.size`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url-search-params.size.js).
[`URL` standard](https://url.spec.whatwg.org/) implementation. Modules [`web.url`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url.js), [`web.url.can-parse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url.can-parse.js), [`web.url.to-json`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url.to-json.js), [`web.url-search-params`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url-search-params.js), [`web.url-search-params.delete`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url-search-params.delete.js), [`web.url-search-params.has`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url-search-params.has.js), [`web.url-search-params.size`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.url-search-params.size.js).
```js
class URL {
constructor(url: string, base?: string);
Expand All @@ -3263,10 +3263,10 @@ class URL {
class URLSearchParams {
constructor(params?: string | Iterable<[key, value]> | Object);
append(name: string, value: string): void;
delete(name: string): void;
delete(name: string, value?: string): void;
get(name: string): string | void;
getAll(name: string): Array<string>;
has(name: string): boolean;
has(name: string, value?: string): boolean;
set(name: string, value: string): void;
sort(): void;
toString(): string;
Expand All @@ -3286,7 +3286,7 @@ core-js(-pure)/stable|actual|full/url/can-parse
core-js/stable|actual|full/url/to-json
core-js(-pure)/stable|actual|full/url-search-params
```
[*Examples*](https://tinyurl.com/2ovt23zn):
[*Examples*](https://tinyurl.com/2j35uor6):
```js
URL.canParse('https://login:password@example.com:8080/?a=1&b=2&a=3&c=4#fragment'); // => true
URL.canParse('https'); // => false
Expand Down Expand Up @@ -3322,16 +3322,21 @@ const params = new URLSearchParams('?a=1&b=2&a=3');

params.append('c', 4);
params.append('a', 2);
params.delete('a', 1);
params.sort();

console.log(params.size); // => 5
console.log(params.size); // => 4

for (let [key, value] of params) {
console.log(key); // => 'a', 'a', 'a', 'b', 'c'
console.log(value); // => '1', '3', '2', '2', '4'
console.log(key); // => 'a', 'a', 'b', 'c'
console.log(value); // => '3', '2', '2', '4'
}

console.log(params.toString()); // => 'a=1&a=3&a=2&b=2&c=4'
console.log(params.has('a')); // => true
console.log(params.has('a', 3)); // => true
console.log(params.has('a', 4)); // => false

console.log(params.toString()); // => 'a=3&a=2&b=2&c=4'
```

##### Caveats when using `URL` and `URLSearchParams`:[⬆](#index)
Expand Down
8 changes: 8 additions & 0 deletions packages/core-js-compat/src/data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2509,6 +2509,14 @@ export const data = {
node: '10.0',
safari: '14.0',
},
'web.url-search-params.delete': {
firefox: '115',
node: '20.2.0',
},
'web.url-search-params.has': {
firefox: '115',
node: '20.2.0',
},
'web.url-search-params.size': {
chrome: '113',
deno: '1.32',
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,7 @@ export default {
'esnext.promise.with-resolvers',
'esnext.symbol.is-registered-symbol',
'esnext.symbol.is-well-known-symbol',
'web.url-search-params.delete',
'web.url-search-params.has',
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// empty
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// empty
4 changes: 3 additions & 1 deletion packages/core-js/internals/url-constructor-detection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ module.exports = !fails(function () {
// eslint-disable-next-line unicorn/relative-url-style -- required for testing
var url = new URL('b?a=1&b=2&c=3', 'http://a');
var searchParams = url.searchParams;
var searchParams2 = new URLSearchParams('a=1&a=2');
var result = '';
url.pathname = 'c%20d';
searchParams.forEach(function (value, key) {
searchParams['delete']('b');
result += key + value;
});
return (IS_PURE && !url.toJSON)
searchParams2['delete']('a', 2);
return (IS_PURE && (!url.toJSON || !searchParams2.has('a', 1) || searchParams2.has('a', 2)))
|| (!searchParams.size && (IS_PURE || !DESCRIPTORS))
|| !searchParams.sort
|| url.href !== 'http://a/c%20d?a=1&c=3'
Expand Down
30 changes: 19 additions & 11 deletions packages/core-js/modules/web.url-search-params.constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,32 +214,37 @@ defineBuiltIns(URLSearchParamsPrototype, {
// `URLSearchParams.prototype.append` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-append
append: function append(name, value) {
validateArgumentsLength(arguments.length, 2);
var state = getInternalParamsState(this);
validateArgumentsLength(arguments.length, 2);
push(state.entries, { key: $toString(name), value: $toString(value) });
if (!DESCRIPTORS) this.length++;
state.updateURL();
},
// `URLSearchParams.prototype.delete` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-delete
'delete': function (name) {
validateArgumentsLength(arguments.length, 1);
'delete': function (name /* , value */) {
var state = getInternalParamsState(this);
var length = validateArgumentsLength(arguments.length, 1);
var entries = state.entries;
var key = $toString(name);
var $value = length < 2 ? undefined : arguments[1];
var value = $value === undefined ? $value : $toString($value);
var index = 0;
while (index < entries.length) {
if (entries[index].key === key) splice(entries, index, 1);
else index++;
var entry = entries[index];
if (entry.key === key && (value === undefined || entry.value === value)) {
splice(entries, index, 1);
if (value !== undefined) break;
} else index++;
}
if (!DESCRIPTORS) this.length = entries.length;
state.updateURL();
},
// `URLSearchParams.prototype.get` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-get
get: function get(name) {
validateArgumentsLength(arguments.length, 1);
var entries = getInternalParamsState(this).entries;
validateArgumentsLength(arguments.length, 1);
var key = $toString(name);
var index = 0;
for (; index < entries.length; index++) {
Expand All @@ -250,8 +255,8 @@ defineBuiltIns(URLSearchParamsPrototype, {
// `URLSearchParams.prototype.getAll` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-getall
getAll: function getAll(name) {
validateArgumentsLength(arguments.length, 1);
var entries = getInternalParamsState(this).entries;
validateArgumentsLength(arguments.length, 1);
var key = $toString(name);
var result = [];
var index = 0;
Expand All @@ -262,21 +267,24 @@ defineBuiltIns(URLSearchParamsPrototype, {
},
// `URLSearchParams.prototype.has` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-has
has: function has(name) {
validateArgumentsLength(arguments.length, 1);
has: function has(name /* , value */) {
var entries = getInternalParamsState(this).entries;
var length = validateArgumentsLength(arguments.length, 1);
var key = $toString(name);
var $value = length < 2 ? undefined : arguments[1];
var value = $value === undefined ? $value : $toString($value);
var index = 0;
while (index < entries.length) {
if (entries[index++].key === key) return true;
var entry = entries[index++];
if (entry.key === key && (value === undefined || entry.value === value)) return true;
}
return false;
},
// `URLSearchParams.prototype.set` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-set
set: function set(name, value) {
validateArgumentsLength(arguments.length, 1);
var state = getInternalParamsState(this);
validateArgumentsLength(arguments.length, 1);
var entries = state.entries;
var found = false;
var key = $toString(name);
Expand Down
46 changes: 46 additions & 0 deletions packages/core-js/modules/web.url-search-params.delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';
var defineBuiltIn = require('../internals/define-built-in');
var uncurryThis = require('../internals/function-uncurry-this');
var toString = require('../internals/to-string');
var validateArgumentsLength = require('../internals/validate-arguments-length');

var $URLSearchParams = URLSearchParams;
var URLSearchParamsPrototype = $URLSearchParams.prototype;
var append = uncurryThis(URLSearchParamsPrototype.append);
var $delete = uncurryThis(URLSearchParamsPrototype['delete']);
var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
var push = uncurryThis([].push);
var params = new $URLSearchParams('a=1&a=2');

params['delete']('a', 1);

if (params + '' !== 'a=2') {
defineBuiltIn(URLSearchParamsPrototype, 'delete', function (name /* , value */) {
var length = arguments.length;
var $value = length < 2 ? undefined : arguments[1];
if (length && $value === undefined) return $delete(this, name);
var entries = [];
forEach(this, function (v, k) { // also validates `this`
push(entries, { key: k, value: v });
});
validateArgumentsLength(length, 1);
var key = toString(name);
var value = toString($value);
var index = 0;
var dindex = 0;
var found = false;
var entriesLength = entries.length;
var entry;
while (index < entriesLength) {
entry = entries[index++];
if (found || entry.key === key) {
found = true;
$delete(this, entry.key);
} else dindex++;
}
while (dindex < entriesLength) {
entry = entries[dindex++];
if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value);
}
}, { enumerable: true, unsafe: true });
}
26 changes: 26 additions & 0 deletions packages/core-js/modules/web.url-search-params.has.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';
var defineBuiltIn = require('../internals/define-built-in');
var uncurryThis = require('../internals/function-uncurry-this');
var toString = require('../internals/to-string');
var validateArgumentsLength = require('../internals/validate-arguments-length');

var $URLSearchParams = URLSearchParams;
var URLSearchParamsPrototype = $URLSearchParams.prototype;
var getAll = uncurryThis(URLSearchParamsPrototype.getAll);
var $has = uncurryThis(URLSearchParamsPrototype.has);
var params = new $URLSearchParams('a=1');

if (params.has('a', 2)) {
defineBuiltIn(URLSearchParamsPrototype, 'has', function has(name /* , value */) {
var length = arguments.length;
var $value = length < 2 ? undefined : arguments[1];
if (length && $value === undefined) return $has(this, name);
var values = getAll(this, name); // also validates `this`
validateArgumentsLength(length, 1);
var value = toString($value);
var index = 0;
while (index < values.length) {
if (values[index++] === value) return true;
} return false;
}, { enumerable: true, unsafe: true });
}
6 changes: 1 addition & 5 deletions packages/core-js/proposals/url.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
// https://github.com/jasnell/proposal-url
require('../modules/web.url');
require('../modules/web.url.can-parse');
require('../modules/web.url.to-json');
require('../modules/web.url-search-params');
require('../modules/web.url-search-params.size');
require('../web/url');
2 changes: 2 additions & 0 deletions packages/core-js/web/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ require('../modules/web.url');
require('../modules/web.url.can-parse');
require('../modules/web.url.to-json');
require('../modules/web.url-search-params');
require('../modules/web.url-search-params.delete');
require('../modules/web.url-search-params.has');
require('../modules/web.url-search-params.size');
var path = require('../internals/path');

Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/web/url-search-params.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require('../modules/web.url-search-params');
require('../modules/web.url-search-params.delete');
require('../modules/web.url-search-params.has');
require('../modules/web.url-search-params.size');
var path = require('../internals/path');

Expand Down
3 changes: 1 addition & 2 deletions packages/core-js/web/url.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
require('./url-search-params');
require('../modules/web.url');
require('../modules/web.url.can-parse');
require('../modules/web.url.to-json');
require('../modules/web.url-search-params');
require('../modules/web.url-search-params.size');
var path = require('../internals/path');

module.exports = path.URL;
9 changes: 9 additions & 0 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1956,6 +1956,15 @@ GLOBAL.tests = {
return URL.prototype.toJSON;
}],
'web.url-search-params.constructor': URL_AND_URL_SEARCH_PARAMS_SUPPORT,
'web.url-search-params.delete': [URL_AND_URL_SEARCH_PARAMS_SUPPORT, function () {
var params = new URLSearchParams('a=1&a=2');
params['delete']('a', 1);
return params + '' === 'a=2';
}],
'web.url-search-params.has': [URL_AND_URL_SEARCH_PARAMS_SUPPORT, function () {
var params = new URLSearchParams('a=1');
return params.has('a', 1) && !params.has('a', 2);
}],
'web.url-search-params.size': [URL_AND_URL_SEARCH_PARAMS_SUPPORT, function () {
return 'size' in URLSearchParams.prototype;
}]
Expand Down
21 changes: 21 additions & 0 deletions tests/unit-global/web.url-search-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,18 @@ QUnit.test('URLSearchParams#delete', assert => {
params.delete('first');
assert.false(params.has('first'), 'search params object has no "first" name');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
params.delete('a', 2);
assert.same(String(params), 'a=1&a=null&a=3&b=4');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
params.delete('a', null);
assert.same(String(params), 'a=1&a=2&a=3&b=4');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
params.delete('a', undefined);
assert.same(String(params), 'b=4');

if (DESCRIPTORS) {
let url = new URL('http://example.com/?param1&param2');
url.searchParams.delete('param1');
Expand Down Expand Up @@ -380,6 +392,15 @@ QUnit.test('URLSearchParams#has', assert => {
params.delete('first');
assert.false(params.has('first'), 'search params object has no name "first"');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
assert.true(params.has('a', 2));
assert.true(params.has('a', null));
assert.false(params.has('a', 4));
assert.true(params.has('b', 4));
assert.false(params.has('b', null));
assert.true(params.has('b', undefined));
assert.false(params.has('c', undefined));

assert.throws(() => {
return new URLSearchParams('').has();
}, 'throws w/o arguments');
Expand Down
21 changes: 21 additions & 0 deletions tests/unit-pure/web.url-search-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,18 @@ QUnit.test('URLSearchParams#delete', assert => {
params.delete('first');
assert.false(params.has('first'), 'search params object has no "first" name');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
params.delete('a', 2);
assert.same(String(params), 'a=1&a=null&a=3&b=4');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
params.delete('a', null);
assert.same(String(params), 'a=1&a=2&a=3&b=4');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
params.delete('a', undefined);
assert.same(String(params), 'b=4');

if (DESCRIPTORS) {
let url = new URL('http://example.com/?param1&param2');
url.searchParams.delete('param1');
Expand Down Expand Up @@ -373,6 +385,15 @@ QUnit.test('URLSearchParams#has', assert => {
params.delete('first');
assert.false(params.has('first'), 'search params object has no name "first"');

params = new URLSearchParams('a=1&a=2&a=null&a=3&b=4');
assert.true(params.has('a', 2));
assert.true(params.has('a', null));
assert.false(params.has('a', 4));
assert.true(params.has('b', 4));
assert.false(params.has('b', null));
assert.true(params.has('b', undefined));
assert.false(params.has('c', undefined));

assert.throws(() => {
return new URLSearchParams('').has();
}, 'throws w/o arguments');
Expand Down