Disabling nonstandard RegExp functionalities for proper subclasses of RegExp

Andrea Giammarchi andrea.giammarchi at gmail.com
Wed Apr 27 04:50:24 UTC 2016

My 2 cents.

I always had the feeling people complaining about `RegExp.$1` and friends
never really used them.

For instance, your example:


might have side effects but it's also made up and, I believe, not a
real-world concern.
If you use `re.exec` you address it, otherwise you go `re.test` while if
you use `re.test` you (or at least *me*) are aware of possible side effects
and will use the `RegExp.$1` or other property *instantly* after.

Following just a simple example:

if (/^item-(\d+)$/.test(id)) {
  let num = parseInt(RegExp.$1, 10);
  // the rest of the code

I'm not saying these properties are cool, always safe, or anything, I'm
just saying there are few useful cases for them.

However, while I agree the problem is that these modify the globally shared
constructor, I also think that having these magic properties available in a
subclass only, would be probably the key to solve pretty much all problems
described in that page.

reg.exp = class extends RegExp {};
function reg(source, ...flags) {
  return typeof source === 'string' ?
    new reg.exp(...[source, ...flags]) :
    new reg.exp(source.source, source.flags);

if (reg(/^item-(\d+)$/).test(id)) {
  let num = parseInt(reg.exp.$1, 10);
  // the rest of the code

  RegExp.$1 === reg.exp.$1; // false
  // the extended RegExp didn't modify
  // the global RegExp

Of course this would still suffer same, or very similar, problems in case
`re.class` is exported as module and consumed by many different libraries,
but I would be surprised if subclassing `RegExp` will create a limited
subset or, at least, I wouldn't call that an extend.

After all, if "safe" is the main concern, writing `class SRegExp extends
RegExp {}` on top of a module that uses RegExp in various ways doesn't look
like a big piece of extra code to write, it's like a function declaration
and it will make your code immune from global RegExp gotchas.

Or ... doesn't it?

Best Regards

On Tue, Apr 26, 2016 at 7:20 PM, Claude Pache <claude.pache at gmail.com>

> Hi,
> About the bad old nonstandard RegExp functionalities:
> * `RegExp.prototype.compile()` — currently in Annex B;
> * `RegExp.$1`, `RegExp.leftContext`, etc. — currently unspecced.
> Although we could probably not get rid of them for plain regexps, I think
> it is a good idea to disable them for proper subclasses of RegExp (e.g.,
> `class MyRegExp extends RegExp {}`).
> Basically, the reason is that these methods break encapsulation (they
> operate on the raw regexp), leading to potential bugs when using them.
> Moreover `RegExp.$1` and friends have the additional troublesome property
> of relying on a global state that could be unexpectedly modified. For
> concrete examples of what could go wrong, see the
> subclass-restriction-motivation.md subpage in the proposal linked below.
> Here is a link to a possible specification for the regexp statics
> (RegExp.$1, ...), that includes the disabling of bad legacy features for
> proper subclasses of RegExp (and for some edge-cases around cross-realm
> interactions):
>      https://github.com/claudepache/es-regexp-legacy-static-properties
> What do you think? Are implementations willing to try?
> —Claude
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160427/e26a7088/attachment-0001.html>

More information about the es-discuss mailing list