Node.js 27のアルファ版が公開、V8 15.6でMathや乱数・メモリの既定値が変わる

V8が14.6から15.6へ、Node.js 27の概要

Node.jsプロジェクトは2026年10月29日(UTC)、Node.js 27.0.0-alpha.0.0.0を公開しました。リリースノートの中心は、JavaScriptエンジンのV8がNode.js 26の14.6から15.6(15.6.75.13)に上がったことです。新しい言語機能が使えるようになる一方、浮動小数点の最下位ビット、乱数列、メモリの既定値など、既存コードやテストに影響しうる変更も入っています。ここではNode.js公式ブログの3本の記事をもとに、Node.js 27で何が変わるのかを整理します。

既定で使える新しい言語機能

V8 15.6で、次の機能が既定で有効になっています。

  • Math.sumPrecise():数値を合計するときに、浮動小数点誤差がたまりにくくなります。公式の例では、[0.1, 0.2, 0.3]をreduceで足すと0.6000000000000001になる一方、Math.sumPreciseでは0.6になります。
  • Intl.Locale.prototype.variants:ロケールのバリアントを取り出すゲッターです。
  • Iterator.prototype.join()とIterator.prototype.includes():イテレーターから直接、文字列結合や存在確認ができます。
  • Iterator.zip()とIterator.zipKeyed():複数のイテレーターを組にして取り出せます。

フラグの背後にある実験的機能としては、import defer(--js-defer-import-eval)、Immutable ArrayBuffer(--js-immutable-arraybuffer)、RegExpのバッファ境界(--js-regexp-buffer-boundaries)が挙げられています。import ... with { type: "bytes" }は、V8側のフラグはあるもののNode.jsではまだ実装されていません。

既存コードに効く挙動の変更

リリースノートは、V8の更新で観測可能な挙動が変わる箇所をまとめています。テストで固定値を比較しているコードは特に注意が必要です。

  • Mathの一部のメソッドがLLVMのlibmを使うため、入力によっては最下位ビットの違いで結果が変わります。たとえばMath.sin(18)は、v26の-0.7509872467716762からv27では-0.750987246771676になります。古いNode.jsの結果を固定値として比較しているコードが、壊れる可能性があります。
  • Math.random()がxorshift128+を直接実行する形になり、--random-seedに同じ値を指定しても、v26とは別の列が返ります(公式の例では、シード42で0.6159…から0.2287…に変わっています)。
  • Date.prototype.getTimezoneOffset()が分単位に切り捨てられなくなりました。標準時を採用する前の歴史的な日付では、小数が返ることがあります。
  • 大きな配列のArray.prototype.sort()がTimSortではなくPowerSortになりました。安定ソートで、一貫した比較関数なら結果は同じですが、比較関数の呼び出し回数を記録するテストや、副作用のある比較関数は挙動が変わりえます。
  • error.stackがプロトタイプチェーンをたどって探索されなくなりました。
  • awaitで発生するマイクロタスクが減りました。

メモリの既定値とシリアライズ形式が変わる

運用で見落としやすいのは、メモリ周りだと見られます。--max-old-space-sizeを指定しない場合、ヒープの上限は物理メモリの半分(256MBから4GBの範囲に収める)が既定になります。物理メモリが4〜15GBのマシンでは、従来より上限が増える場合があります(V8の解説記事によれば、8GBのマシンは2GBから4GBへ)。また、BufferやArrayBufferが保持するメモリもヒープ上限に数えられるようになり、GCが走るタイミングにも影響します。リリースノートは、従来の既定値に頼っていたアプリは--max-old-space-sizeを明示するよう求めています。

さらに、v8.serialize()、structuredClone()、postMessage()が新しい形式を使い、古いNode.jsでは読み込めません。v8.cachedDataVersionTag()やコンパイルキャッシュも、V8のバージョンが同じでも、Node.jsがV8に当てる独自パッチが変わるたびに変わります。ヒープスナップショットは内部オブジェクトや数値、スクリプトの全ソースを含むようになり、取得に約2倍の時間がかかり、ファイルも約2倍の大きさになります。WebAssemblyでは、asm.jsがWebAssemblyにコンパイルされなくなり、--experimental-wasm-<name>系のフラグが--wasm-<name>に改名されました。

OpenSSL 3必須化など、ビルドとcrypto周りの破壊的変更

リリースノートの「その他の主な変更」には、SEMVER-MAJORの項目が並んでいます。同梱FIPSプロバイダーのビルドの削除、OpenSSL 3以降の必須化、Intel macOSサポートの実験的扱いへの格下げ、DEP0093のEnd-of-Life化、レガシーなOpenSSLコードパスの削除などです。このほかにも多数の項目があるので、ネイティブアドオンやOpenSSLに依存するビルドを自前で行っている場合は、原文で一覧を確認してください。

アルファ版をどう扱うか

公式ブログによると、Node.jsはアルファ段階を持つ新しいリリーススケジュールに移行します。そのためアルファとCurrentの期間中には、V8の一括アップグレードのような破壊的変更が入りうるとされています。ネイティブアドオンのABIに影響する変更にはNODE_MODULE_VERSIONの更新が伴うため、ABIバージョンをもとにビルド済みアドオンを選ぶツールチェーンは、動き続けられる想定です。27がLTSに入ったあとは、V8のバージョンは安定し、重大なセキュリティ修正などの例外を除いてABIやAPIの破壊的変更は想定されていません。

筆者は、アルファ版は本番には使わず、CIの「先行確認枠」に1本足す使い方が現実的だと考えます。特に確認したいのは、上で挙げた「固定値のスナップショットテスト」「乱数のシード固定」「ヒープ上限に依存した設定」の3点です。コードの不具合ではなくテストの前提が崩れるだけのことも多いと考えられますが、LTSに入る前に洗い出しておけば、移行時の手戻りを減らせます。これは公式の推奨ではなく筆者の見解です。

あわせて確認したい、11月11日のセキュリティリリース

同じNode.jsのブログには、2026年11月11日(水)にセキュリティリリースが予定されているとの告知が出ています。対象は26.x、24.x、22.xの各系統で、いずれも最も深刻度の高い修正はHIGHとされています。告知は11月3日(UTC)に公開されており、リリースは当日またはその直後になる見込みです。取得した時点では修正内容の詳細は載っていなかったため、リリース後に更新を確認してください。End-of-Lifeのバージョンは、セキュリティリリースのたびに影響を受けるため、サポート中の系統に上げておくことが推奨されています。

出典

2026年11月6日時点の情報です。

PR当サイトはアフィリエイト広告を利用しています。掲載内容は広告主から依頼・指示を受けたものではなく、筆者の調査・体験にもとづきます。
タイトルとURLをコピーしました