| Summary: | String.prototype.replace should not take fast path if the pattern is RegExp Object and the lastIndex is not numeric | ||
|---|---|---|---|
| Product: | WebKit | Reporter: | EntryHi <entryhii> |
| Component: | JavaScriptCore | Assignee: | Nobody <webkit-unassigned> |
| Status: | RESOLVED FIXED | ||
| Severity: | Normal | CC: | karlcow, mark.lam, msaboff, webkit-bug-importer, ysuzuki |
| Priority: | P2 | Keywords: | BrowserCompat, InRadar |
| Version: | WebKit Local Build | ||
| Hardware: | PC | ||
| OS: | Linux | ||
Modified to run in the browser console.
```
for (let i = 0; i < 3000; ++i) {
let r = /abcd/;
regexLastIndex = {};
regexLastIndex.toString = function () {
console.log(i)
return "1";
};
r.lastIndex = regexLastIndex;
"test".replace(r, "cons")
}
```
Safari result is random
Both Firefox and Chrome print until 2999.
Tested on macOS 13.0
---
Safari Technology Preview 155 18615.1.7.1
Firefox Nightly 107.0a1 10722.10.4
Google Chrome Canary 108.0.5355.0 5355.0
Pull request: https://github.com/WebKit/WebKit/pull/24959 Committed 275255@main (3790f1e3cc0a): <https://commits.webkit.org/275255@main> Reviewed commits have been landed. Closing PR #24959 and removing active labels. |
for (let i = 0; i < 3000; ++i) { let r = /abcd/; regexLastIndex = {}; regexLastIndex.toString = function () { print(i) return "1"; }; r.lastIndex = regexLastIndex; "test".replace(r, "cons") } With the above script as input to JSC, run JSC with the following parameters: ./jsc test.js --useConcurrentJIT=0 This bug is similar to 191731, but they are different. The above js scripts should print 0-2999, but jsc only prints 0-2209. In DFGBytecodeParser, replace is inlined into StringReplace node. In DFGStrengthReduction, StringReplace is converted to Identity. So after DFG, lastIndex is no longer read and updated. Therefore, regexLastIndex.toString is no longer invoked.