今回のNode.jsは、WebAssemblyを使えない環境で機能を呼び出すと、原因を区別できるエラーを返すようになった。制限された実行環境を扱う開発者は失敗原因を把握しやすくなり、WebSocketライブラリの開発者は送信データのマスクと解除の処理を組み込み機能に移せる。

公式リリース記事は、2026年10月14日に公開された今回のバージョンの主な変更として、この2項目を挙げた。いずれもマイナー変更に分類された。

1. 非対応環境での失敗原因を区別する

WebAssemblyは、別途コンパイルされたモジュールを実行する技術だ。エラー処理の変更説明によると、これを使えない環境で該当モジュールをインポートするとERR_WEBASSEMBLY_NOT_SUPPORTEDが発生する。プログラムで捕捉して処理できるエラーによって、機能が利用できないことを知らせる仕組みだ。

ただし、エラー処理の変更を、以前は失敗しなかった機能が新たに失敗するものと捉えてはならない。レビューでの議論では、すでに発生していたエラーをより適切に知らせる改善だと説明された。

外部ライブラリ関数を高速に呼び出す経路も対象だ。他の呼び出し要件を満たしていても、読み取りと実行が可能なメモリのサポート確認に失敗すると、ERR_RX_MEMORY_NOT_SUPPORTEDで原因を知らせる。コールバックの割り当て失敗後もこのサポート状況を診断するが、プラットフォームごとの静的な呼び出し接続方式と他のエラーは維持する。

必要な実行能力がない場合に代替経路を保証しないことも、文書に明記された。つまり、エラーを捕捉できることは、別の方法でその機能を実行してくれることを意味しない。JITコンパイルを無効にした実行と、Linuxのシステムコール制限環境に対する回帰テストも追加された。

2. WebSocketの反復処理を組み込み機能に移す

WebSocketのクライアントは、送信するフレーム、つまり転送単位ごとに4バイトのキーを繰り返し適用し、データをマスクする。サーバーは同じ処理でマスクを解除する。両方のビットが異なると1になる排他的論理和を適用するため、同じキーを再び使うと元のデータに戻る。

http.websocketMask()は元データと出力先を受け取ってマスク処理を行い、http.websocketUnmask()は受信したバッファ自体のマスクを解除する。汎用的なデータマスクではなく、WebSocketで定められたキー長に合わせた機能だ。

既存のネイティブ拡張モジュールであるbufferutilと引数の形式を合わせた。そのため、これを使っていたライブラリは新関数の有無を確認してから切り替えられる。変更提案の作成者は、この拡張のインストール率をwsのダウンロード数の約3%と説明し、残りの利用者は主にJavaScriptのループに依存していると述べた。

3. キーを用意する責任は残る

マスクは、メモリの一定区間を参照するArrayBufferViewとして受け取る。レビューでは数値配列も受け付ける提案ではなく、既存の拡張との互換性を維持した。作成者は、通信ライブラリの既存バッファから4バイトの区間を取り出し、フレームごとの配列割り当てを避ける方法を提案した。原文にある式は次のとおりだ。

buffer.subarray(bufIdx, bufIdx += 4)

これは新関数の完全な呼び出し例ではなく、キーを格納するメモリ区間を取得する式だ。処理が組み込まれても、キーの選択まで省略できるわけではない。レビューで引用された仕様は、フレームごとに予測困難な新しいキーを要求しており、サーバーには実際にマスクされたデータが届くことも指摘された。

4. 性能向上は入力サイズと併せて読むべきだ

WebSocket変更のコミット説明では、JavaScriptのループに比べ、1 KiBの入力で約20倍、64 KiBで約40倍速いとされた。既存の拡張より速い範囲は32バイト以上と示された。一方、作成者は24バイト未満では内部関数の呼び出しコストによりループの方が速いと説明した。測定に使ったハードウェアとOSは示されなかった。

利点は、別途拡張をインストールせずに反復処理を組み込み実装へ移せることだ。一方、ライブラリ開発者には、旧バージョンでの機能の有無の確認や、入力サイズに応じた経路選択を検討する作業が残る。したがって、提示された処理速度の差を、WebSocketサービス全体のスループット向上と読み替えない方が妥当だ。

今回のバージョンは、一般的なアプリケーションの機能拡大よりも、制限された実行環境やWebSocket実装を扱う開発者にとって意義の大きい更新だ。