Chrome 75正则表达式,'S'匹配奇怪的Unicode范围



我们在最新版本的Chrome(75)上有一个奇怪的错误,它将S替换为S

console.log(
'AZERTYUIOPQSDFGHJKLMWXCVBN'.replace(/[u00A0-u9999<>&]/gim, char => `&#${char.charCodeAt(0)};`)
)

//AZERTYUIOPQ&#83;DFGHJKLMWXCVBN

有人知道代码是问题还是Chrome是问题吗?

在75.0.3770.142 中修复。


你发现了一个有趣的错误:

由于某些原因,这两个测试是正确的,这取决于不相关的字符范围:

> /[u0178-u017F]/i.test('s')
true
> /[u0178-u017F]/i.test('S')
true

由 https://chromium-review.googlesource.com/c/v8/v8/+/1478710(4月)介绍。

https://chromium-review.googlesource.com/c/v8/v8/+/1648098 中的修复似乎相关,但带有 v8 7.7.27 的 Canary 77.0.3818.0 仍然表现出此行为。这是一个单独的错误:https://crbug.com/971636

引入该问题的错误 (https://bugs.chromium.org/p/v8/issues/detail?id=8348) 讨论了 ECMAScript 如何以不同的方式对待iu

  • 单独调用itoUpperCase,它使用案例映射
  • iu调用 Unicode 大小写折叠

这些略有不同(尽管有此错误)。

我还发现了一个似乎不同的错误:

这是一个小型测试用例,尽管 v8 中的修复是指土耳其案例折叠:

> text='ſ';
"ſ"
> new RegExp(text, 'i').test(text.toUpperCase())
true
> new RegExp(text, 'i').test('S')
false

它是在同一修订版中引入的,但它并不完全相同 - 它特定于s 字符,其大写版本位于 ASCII 范围内,因此在 V8 的正则表达式编译器中触发了不同的代码路径。在 https://chromium-review.googlesource.com/c/v8/v8/+/1827683 单独固定

更改为:

'S'.replace(/[u00A0-u017Eu0180-u9999<>&]/gim, char => `&#${char.charCodeAt(0)};`)

将避免使用u017F的 Unicode 字符"拉丁小写字母 LONG S"。这只是一种解决方法。

触发范围的另一端似乎是u0073,即"拉丁小写字母S"。

im的标志在该时间间隔内甚至没有使用,您需要使用标志u它将模式视为 Unicode 代码点的序列。

console.log(
'AZERTYUIOPQSDFGHJKLMWXCVBN'.replace(/[u00A0-u9999<>&]/gu, char => `&#${char.charCodeAt(0)};`)
)

我在Chrome 75中看到同样的问题,但没有看到Chrome 74。此问题已通过使用以下正则表达式修复:

'AZERTYUIOPQSDFGHJKLMWXCVBN'.replace(/[u00A0-u9999<>&]/g, char => `&#${char.charCodeAt(0)};`)

正如一些评论中提到的,我认为您不需要 i、u 或 m 修饰符。

最新更新