Bug 216671

Summary: Regex: optional start of string assertion fails
Product: WebKit Reporter: Justin Ridgewell <jridgewell>
Component: JavaScriptCoreAssignee: Michael Saboff <msaboff>
Status: ASSIGNED ---    
Severity: Normal CC: keith_miller, msaboff, saam, tzagallo, webkit-bug-importer, ysuzuki
Priority: P2 Keywords: InRadar
Version: Safari Technology Preview   
Hardware: Unspecified   
OS: Unspecified   

Description Justin Ridgewell 2020-09-17 16:15:39 PDT
Re: https://github.com/Polymer/lit-html/pull/1218#discussion_r489158205

We've discovered that Safari's regex engine fails to match optional start of string position assertions, eg `/(^a)?B/`.

```js
const cases = [
  'aB',
  'bB',
  'B',
];

for (const s of cases) {
  if (!/(^a)?B/.test(s)) {
    throw new Error(s);
  }
}
```

Open your console on https://output.jsbin.com/finowid/1/quiet to see it run.
Comment 1 Radar WebKit Bug Importer 2020-09-17 17:17:00 PDT
<rdar://problem/69107160>
Comment 2 Yusuke Suzuki 2020-11-14 01:49:38 PST
Michael, can you take a look?
Comment 3 Michael Saboff 2020-11-15 10:18:59 PST
The problem happens in the YARR JIT.  The interpreter properly handles this case.

More investigation.
Comment 4 Michael Saboff 2020-11-20 10:57:20 PST
The issue appears to be the beginning of line (BOL) "run once" optimization is triggered for this regular expression and shouldn't be.  I verified that we properly matched the test strings with the provided RegExp when I disabled the run once optimization.

The run once optimization is triggered when all alternatives begin with ^.  During parsing if the first term of an alternative is ^, we flag the alternative as starting with BOL.  In the case of groups this happens before the group's min/max counts are parsed.  The fix is to factor in a minimum count of 0 when setting the flag indicating that an alternative is BOL anchored.  The BOL anchor flag setting needs to be done after the counts are parsed or modified for grouped matches with a minimum count of 0.