1 of 6

ECMAScript RegExp semantics tweaks

Daniel Ehrenberg (Google)

Michael Saboff (Apple)

2 of 6

RegExpBuiltinExec flag access

  • The initial value of RegExp.prototype.exec
  • Type checks receiver to ensure RegExp instance
  • Two ways to access flags
    • Getters: g, y
    • [[OriginalFlags]]: u and, in the matcher, i, m, and u

3 of 6

Proposal: Always use [[OriginalFlags]]

  • Disadvantages
    • Subclassing? Make the getters return different values at different times
  • Advantages
    • Consistency: When you check for [[RegExpMatcher]], use [[OriginalFlags]]
    • Implementation complexity: Engines tend to compile y into the matcher
    • Subclassing: Variable getters might not halt; hard to imagine use case

4 of 6

RegExp feature testing web compatibility

  • ES2015: RegExp.prototype is an ordinary object
    • No [[RegExpMatcher]] or other internal slots
  • ES2015: Flags are getters on RegExp.prototype
    • Which type check the receiver to ensure it is a RegExp
  • Result: ES2015 says the following throw:
    • RegExp.prototype.sticky
    • RegExp.prototype.toString()
    • RegExp.prototype.flags

5 of 6

All of these are found on the web!

  • Chrome has a couple UseCounters now (more in the works)
    • RegExp.prototype.sticky -- 0.0534% of documents
      • Used by older versions of XRegExp 2.0, es5-ext
    • RegExp.prototype.toString()-- 0.0155% of documents
      • Unknown use case (browser detection?)
  • Other bug reports
    • RegExp.prototype.flags
      • Old versions of es6shim
    • Significantly older versions of core-js also used many of these
  • RegExp.prototype.source throws in ES2015, but no documented risk

6 of 6

Workaround: Make it not throw

  • V8 ships these semantics today:
    • Flag getters:
      • If there is no [[OriginalFlags]] internal slot,
        • If the receiver is RegExp.prototype, return undefined
        • Else, throw a TypeError
    • RegExp.prototype.toString():
      • If there is no [[RegExpMatcher]] internal slot,
        • If the receiver is RegExp.prototype, return “/(?:)/”
        • Else, throw a TypeError
  • Other possibilities
    • Return false sometimes? Handle RegExp.prototype.source?