◆ ブラウザで oniguruma 正規表現が使える
◆ JavaScript ネイティブのほうが速い
◆ oniguruma 正規表現のみの機能が必要なときくらい?

Github で見かけたライブラリ
https://github.com/NeekSandhu/onigasm

正規表現の oniguruma の WebAssembly 版らしいです

名前は最初見たとき 『鬼が棲む』 って読んでたのですが oniguruma の onig と WebAssembly の asm の合体のようです

使ってみた

node-oniguruma と同じようにつかえるみたいなので Node.js 用なのかなと思いました
でも ソースを見てみると loadASM で fetch を使っていたりでブラウザ用な気もします
https://github.com/NeekSandhu/onigasm/blob/v2.2.4/src/onigasmH.ts#L56

ただ ブラウザで使おうにも そのままでは ESModules としてロードはできないです
バンドルするしか無いので Webpack を使ってブラウザで使ってみることにしました

まずはインストールします

npm install onigasm

「node_modules/onigasm/lib/onigasm.wasm」 を fetch でロードするのでこれをパッケージのルートにコピーしておきます

[index.js]
import { loadWASM, OnigRegExp, OnigScanner } from "onigasm"

loadWASM("onigasm.wasm").then(() => {
const ore = new OnigRegExp(/(\d+) (\d+)/.source)
console.log(ore.searchSync("a b 1 23 4 c d"))
ore.search("a b 1 23 4 c d", (err, matched) => console.log(matched))
})

loadWASM で onigasm.wasm をロードしたら OnigRegExp などを使えます
正規表現の source は文字列指定しないといけないみたいで それだとエスケープが面倒なので正規表現リテラルの source プロパティを渡すことにしました
デフォルトは非同期みたいで 同期的に実行するには Node.js の API みたいに Sync をつければ良いようです

これを Webpack でバンドルします

webpack index.js --mode=development --output=bundle.js

最後に表示用の HTML を用意します

<!doctype html>
<script src="bundle.js"></script>

この HTML ファイルを開いてコンソールを見ると

(3) [{…}, {…}, {…}]
0: {end: 8, index: 0, length: 4, start: 4, match: "1 23"}
1: {end: 5, index: 1, length: 1, start: 4, match: "1"}
2: {end: 8, index: 2, length: 2, start: 6, match: "23"}
length: 3
__proto__: Array(0)

(3) [{…}, {…}, {…}]
0: {end: 8, index: 0, length: 4, start: 4, match: "1 23"}
1: {end: 5, index: 1, length: 1, start: 4, match: "1"}
2: {end: 8, index: 2, length: 2, start: 6, match: "23"}
length: 3
__proto__: Array(0)

マッチした部分全体とカッコのキャプチャ部分が取得できています

速いの?

README.md によれば V8 のルートにフックできないから node-oniguruma より 2 倍遅くなるそうです
用途はやっぱり WebAssembly 対応ブラウザで動かすことでしょうか
ブラウザでは Node.js と違って C++ 拡張使えませんし

ネイティブの正規表現と速度比較してみました

import { loadWASM, OnigRegExp, OnigScanner } from "onigasm"

loadWASM("onigasm.wasm").then(() => {
case_ore()
case_re()
case_ore()
case_re()
case_ore()
case_re()
})

const case_ore = () => {
const ore = new OnigRegExp("a.b")
console.time("onigasm")
for (let i = 0, s = "b"; i < 1000; i++) {
s = "a" + s
ore.searchSync(s)
}
console.timeEnd("onigasm")
}

const case_re = () => {
const re = /a.b/
console.time("re")
for (let i = 0, s = "b"; i < 1000; i++) {
s = "a" + s
re.exec(s)
}
console.timeEnd("re")
}
onigasm: 118.209716796875ms
re: 2.126220703125ms
onigasm: 69.372314453125ms
re: 2.06689453125ms
onigasm: 55.9951171875ms
re: 1.185791015625ms

ネイティブの正規表現と比べると 2 倍どころか 50 倍くらい差が出てます
検索条件によって差も変わってくると思いますが 基本的にネイティブのほうが速そうです

oniguruma の正規表現じゃないと使えないのがあるなら使う価値はあるのだと思いますが JavaScript ネイティブの正規表現で困ることがないので特に入れなくてもいいかなーというのが感想です

そういえば oniguruma 系には onigumo という改良版もあってサクラエディタの検索はこっちです
こっちのほうが新しそうなのに使われてないのでしょうか(使ってるのは日本だけ?)