Kotlin跨平台SemVer校验时Regex.matches在JS与其他平台行为不一致问询
问题原因分析
- Kotlin的
Regex类在不同平台底层依赖的正则引擎不同:JVM平台依赖Java内置的正则库,Native平台依赖PCRE引擎,JS/Node.js平台依赖JavaScript原生RegExp实现,三者的匹配逻辑存在细微差异。 - 你当前的正则没有显式添加开头
^和结尾$锚定符。Kotlin官方定义matches方法为全字符串匹配,但Kotlin 1.6.0的JS后端并未严格实现该逻辑,底层直接调用了JS的RegExp.test()方法(该方法只要输入中存在匹配子串就返回true,而非全匹配),最终导致跨平台结果不一致。 - 你的正则逻辑本身符合semver.org对预发布版本段的校验规则,测试用例
01s属于合法的预发布标识符:因为标识符包含非数字字符,不受纯数字标识符禁止前导零的约束。
解决方案
- 第一步:给正则补全开头和结尾锚定符,强制要求全字符串匹配,消除不同平台的实现差异:
val preReleasePattern = Regex("""^(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*$""")
- 第二步:如果需要在Kotlin 1.6.0版本下完全兼容JS平台,可通过跨平台的
expect/actual语法,分别为不同平台实现校验逻辑:JVM和Native平台继续使用Kotlin标准库Regex,JS平台直接调用原生RegExp并显式指定全匹配规则。 - 第三步:如果条件允许,升级Kotlin版本到1.7.0及以上,该版本修复了JS平台
Regex.matches方法的实现不一致问题。
内容的提问来源于stack exchange,提问作者Eric Li
相关产品推荐
相关产品推荐

