> Le 27 avr. 2016 à 06:50, Andrea Giammarchi <[email protected]> a 
> écrit :
> 
> My 2 cents.
> 
> I always had the feeling people complaining about `RegExp.$1` and friends 
> never really used them.
> 
> For instance, your example:
> 
> ```js
> /(a)/.exec('a')
> Object.keys(bar)
> RegExp.$1
> ```
> 
> 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:
> 
> ```js
> 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.

An important point in my made-up example with `Object.keys()`, is that such an 
apparently innocuous function call might be hidden deep in the subclass 
implementation. That was an illustration of a way (among others) how a 
user-defined subclass could make the built-in RegExp.$1 feature brittle or 
buggy. (And no, I haven't taken time to find a realistic example, and I won't.)

> 
> 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.
> 
> ```js
> 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.

Of course, subclasses of RegExp are free to define their own `reg.exp.$1` 
static properties, insomuch that they are free to implement features that other 
people judge horrific.

In any case, it might be good that `reg.exp.$1` does not inherit from 
`RegExp.$1` by default (as it is currently the case), in case the semantics and 
implementation of `reg.exp` renders the value of the inherited property 
misleading.


> 
> 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?

I think that safety is not the main concern here. I mean, safety is better 
served by completely removing RegExp.$1 and friends, including for plain 
regexps, which, although it couldn't be achieved by default, can be made 
possible by leaving to the user the ability to remove completely the API (e.g., 
by making RegExp.$1 configurable and deletable) and by limiting cross-realm 
leaks. I.e., by rendering the entire environment safe instead of leaving that 
task to individual modules.

—Claude

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to