String.prototype.matchAll returns an iterator, not an array

Getting every match with capture groups meant a while loop over regex.exec, mutating lastIndex, with an infinite loop waiting for anyone who forgets the g flag.

const re = /(?<key>w+)=(?<value>[^;]+)/g;

for (const m of header.matchAll(re)) {
  console.log(m.groups.key, m.groups.value);
}

// it is an iterator, so spread it if you need length or indexing
const all = [...header.matchAll(re)];

// and without /g it throws, which is the right failure

Throwing on a non-global regex is a considerable improvement over the old loop, which simply never terminated. The iterator is lazy, so a large input can be processed without materialising every match — and it means the result cannot be iterated twice, which is the one thing to watch. Named capture groups combined with this make a small parser genuinely readable, which was not true of the exec version.