Skip to content

Instantly share code, notes, and snippets.

@TheBrenny
Last active February 24, 2023 19:23
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save TheBrenny/039add509c87a3143b9c077f76aa550b to your computer and use it in GitHub Desktop.
Save TheBrenny/039add509c87a3143b9c077f76aa550b to your computer and use it in GitHub Desktop.
A polyfill for the String.prototype.matchAll method. Only available in Node12+ and most browsers.

I know almost all browsers and Node installations support it, but Node 11 doesn't, and I kinda need that right now. So enjoy!

// Useable just like the normal matchAll:

let data = "Hello World!";
let rx = /[A-Z]/g;
let matches = [...data.matchAll(rx)];

console.table(matches);
/* Expected output:
┌─────────┬─────┬───────┬────────────────┬───────────┐
│ (index) │  0  │ index │     input      │  groups   │
├─────────┼─────┼───────┼────────────────┼───────────┤
│    0    │ 'H' │   0   │ 'Hello World!' │ undefined │
│    1    │ 'W' │   6   │ 'Hello World!' │ undefined │
└─────────┴─────┴───────┴────────────────┴───────────┘
*/
if(!String.prototype.matchAll) {
String.prototype.matchAll = function (rx) {
if (typeof rx === "string") rx = new RegExp(rx, "g"); // coerce a string to be a global regex
rx = new RegExp(rx); // Clone the regex so we don't update the last index on the regex they pass us
let cap = []; // the single capture
let all = []; // all the captures (return this)
while ((cap = rx.exec(this)) !== null) all.push(cap); // execute and add
return all; // profit!
};
}
@ArcaneDiver
Copy link

ArcaneDiver commented Jun 10, 2022

this code dont work, it goes in an infinite loop

@TheBrenny
Copy link
Author

Can you explain what you did to make it go in an infinite loop? Maybe you did something that MDN told you not to do?

@krackers
Copy link

I think there's an edge case this doesn't handle:

matchAll() is not allowed to get "stuck" returning an empty string match infinitely, so we must make sure lastIndex always increases.

See https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/js/es6/string/matchall.js for a more complete polyfill. It doesn't handle unicode, but you can fix that by changing one the advancement based on whether the regex has unicode flag or not (see the link in the comment).

More generally, Closure library is usually a great source for simple yet battle-tested polyfills. (Definitely much better than the

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment