Thanks for the bug report! The fix for this is on github 
(https://github.com/tc39/ecma262/pull/627) and on the agenda for this week’s 
meeting. I hope this will be fixed by next week (though there are some web 
compat concerns).

Thanks,
Brian

From: es-discuss [mailto:[email protected]] On Behalf Of Duane 
Leslie
Sent: Sunday, February 28, 2016 4:16 PM
To: [email protected]
Subject: Inconsistent gating of `Set(_, "lastIndex", _, true)` in Regular 
Expressions breaks frozen instances.

In most cases [[Set]] operations on the `lastIndex` property of regular 
expressions is gated by the 'global' and/or 'sticky' flags*.  This should mean 
that a non-global/non-stick regular expression can be safely frozen.  
Unfortunately two cases have not been gated, and in both of these cases the 
operation is a no-op except that it results in a thrown TypeError.
Specifically, '21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec', step 12.a.i 
sets the `lastIndex` to 0 if the match fails to occur regardless of the flags 
or the original state of `lastIndex`.  If the regular expression is 
non-global/non-sticky the `lastIndex` property can never be non-zero so this is 
a no-op that throws.
Additionally, in '21.2.5.9 RegExp.prototype [ @@search ]' steps 5 & 7 blindly 
reset and restore the `lastIndex` value without checking the global or sticky 
flags.  Assuming the `RegExpBuiltinExec` is used then Step 5 is a no-op that 
throws since the `lastIndex` cannot be non-zero, and step 7 is a no-op that 
throws since the `lastIndex` can only be set to 0 (or not modified) by 
`RegExpBuiltinExec`.  The attached NOTE states "The `lastIndex` property is 
left unchanged" which is not entirely true.
The problem with the throw in `RegExpBuiltinExec` that particularly troubles me 
is that it only occurs if the match fails.  So long as the match succeeds a 
frozen non-global/non-sticky regular expression will work correctly through 
this method.  If however the match fails instead of returning `null` a 
TypeError will be thrown.

For completeness, the only other non-gate [[Set]] of `lastIndex` is in 
'21.2.3.2.2 Runtime Semantics: RegExpInitialize' step 12 which is only called 
with an existing object through 'B.2.5.1 RegExp.prototype.compile'.  I have no 
position either way on whether this instance should be gated somehow.  All of 
the other initialized values are internal properties and so unaffected by being 
frozen, so maybe it is best that the `lastIndex` always throws so that a frozen 
`RegExp` cannot be changed by a call to `.compile()`.

[*] Gated [[Set]]:
    21.2.5.2.2 step 12.c.i.1 (sticky)
    21.2.5.2.2 step 15 (global || sticky)
    21.2.5.6 step 6.b (global)
    21.2.5.6 step 6.e.iii.4.c (global)
    21.2.5.8 step 8.b (global)
    21.2.5.8 step 11.c.iii.2.c (global)
    21.2.5.11 step 19.a (sticky, supplied `rx` is copied first)

Regards,

Duane.

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

Reply via email to