node icon indicating copy to clipboard operation
node copied to clipboard

delete searchParams during iteration will cause skipping

Open beenotung opened this issue 7 months ago • 1 comments

Version

v22.13.1

Platform

Linux BeenoTung-Archlinux-laptop-kudu 6.14.9-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 29 May 2025 21:42:15 +0000 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

When running below code in nodejs

let url = new URL('http://example.com?a=1&b=2&c=3&d=4')
let { searchParams } = url

console.log('all keys:', Array.from(searchParams.keys()))

for (let key of searchParams.keys()) {
  console.log('delete:', { key })
  searchParams.delete(key)
}

console.log('remains keys:', Array.from(searchParams.keys()))

How often does it reproduce? Is there a required condition?

The behavior can be reproduced every time, without additional condition.

What is the expected behavior? Why is that the expected behavior?

The expected behavior is to delete all params.

Workaround is to collect all elements into an array then iterate on the array, instead of iterate on the iterator directly, which is not intuitive IMO.

What do you see instead?

The observed output is listed as below

all keys: [ 'a', 'b', 'c', 'd' ]
delete: { key: 'a' }
delete: { key: 'c' }
remains keys: [ 'b', 'd' ]

Only the odd index keys are deleted.

Additional information

No response

beenotung avatar Jun 15 '25 16:06 beenotung

this will happen as you are deleting from array, so the array size is getting smaller but the iterator continues to increment. step 0: array:[a,b,c,d] ; i = 0 ; array[i] = a step 1: array: [b,c,d] (we deleted a ) ; i = 1; array[i] = c after deleting 'c' iterator i gets larger than the size of array so loop stops

sayymeer avatar Jun 15 '25 17:06 sayymeer

It is actually the expected behavior. .keys() is providing the iterator for the keys of the URLSearchParams. When the internal state of the URLSearchParams changed, it should also be updated immediately.

It is also why you need to use Array.from when you do the console.log. Because the provided value is not an array but iterator of internal state.

climba03003 avatar Jun 16 '25 02:06 climba03003

As this is expected behavior, I'm closing this

juanarbol avatar Jun 17 '25 05:06 juanarbol

thanks for the clarification, then we've to wrap it with Array.from() if we plan to delete elements when iterating 👌

beenotung avatar Jun 23 '25 10:06 beenotung