V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
lisongeee
V2EX  ›  分享创造

分享一种借助 Kotlin/Wasm 在 JavaScript 中使用一致的 Kotlin/ Java 正则表达式的方案

  •  1
     
  •   lisongeee ·
    lisonge · 33 天前 · 1614 次点击
    这是一个创建于 33 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为什么会有这个需求

    起因是我给我自己编写的 高级选择器 增加了 ~= 操作符(等价 Kotlin/Java 里的 String.mtches 函数)

    比如 [text~='ikun?'] 简单匹配 text 属性为 ikun 或者 iku 的节点

    这个代码需要同时在 Android浏览器 上运行,源代码是基于 Kotlin Multiplatform 构建,可以直接编译到 JavaScript

    但是涉及到正则表达式,它在 Kotlin/Js 这块的 Regex 对象只是对 JavaScript 的 RegExp 的简单封装,缺失了很多特性,并没有真正实现跨平台一致

    比如 (?im)abc 这个正则表达式在 Kotlin/Jvm 上被正常编译,但 RegExp 不支持此正则语法,所以在 Kotlin/Js 上运行后提示非法正则

    也可以在 KT-49065 找到类似的问题,所以为了保持一致性,我需要解决在 JavaScript 上使用的问题

    解决此问题的历程

    我一开始想着看看有没有人用 JavaScript 手动实现 Kotlin/Java 正则表达式,有的话我直接 pnpm add 就完了

    搜遍了 www.npmjs.com 果然没有,看来是这个需求太小众了么

    后面我又找到 regex101.com,看起来它在网页上实现了 Java8 的正则表达式解析和匹配

    可惜它不是开源的,在 Github 找到的相关代码也是编译压缩后的产物

    然后我找到了 openjdk17 的 java/util/regex/Pattern.java 的源代码,想着手动转译实现吧

    但是看着如此庞大的代码,我一个 BUG 制造机器还是放弃了

    最后想到了 Kotlin Multiplatform 下的 Kotlin/Wasm (目前处于实验阶段)

    简单的原理描述就是将 kotlin 代码编译到 wasm 导出对象然后通过在 浏览器 端加载替换匹配函数

    1 . 编译 导出函数到 wasm

    
    @JsExport
    fun toMatches(source: String): (input: String) -> Boolean {
        val regex = Regex(source)
        return { input -> regex.matches(input) }
    }
    

    2 . 在浏览器 加载 这个导出函数并执行替换

    import matchesInstantiate from '@gkd-kit/wasm_matches';
    import matchesWasmUrl from '@gkd-kit/wasm_matches/dist/mod.wasm?url';
    
    matchesInstantiate(fetch(matchesWasmUrl))
      .then((mod) => {
        const toMatches = mod.exports.toMatches;
        updateWasmToMatches(toMatches);
      })
    

    关键流程就两步,看起来其实也挺简单的

    说一下 Kotlin/Wasm 需要浏览器支持 WasmGC,也就是版本需要满足下列条件

    image

    如果你的浏览器不满足条件,会有一个提示弹窗并自动回退到原来的 JavaScript RegExp 实现

    实际体验

    你可以在 https://i.gkd.li/i/14045424 使用选择器查询 [text~=".*[0-9].*"] 找到属性 text 包含数字的所有节点

    如果你的浏览器版本符合上面说的,那么你能在上述网页里体验到完整的 Kotlin/Java 正则表达式

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2249 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 06:39 · PVG 14:39 · LAX 23:39 · JFK 02:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.