Deno (ディノ) Advent Calendar 2020、20日目の記事です。
今日は Deno 本体のレポジトリのディレクトリ構造を紹介します。(Deno 本体にコントリビュートしたい人、Deno 本体の成り立ちを理解したい人向けの記事です。)
deno/
├── cli
├── core
├── docs
├── op_crates
├── runtime
├── std
├── test_plugin
├── test_util
├── third_party
└── tools
現在 Deno のトップレベルのディレクトリは上記の10個です (ドットで始まるものは除く)。
この内、プログラムとしての deno コマンドの中身を実装しているものは、cli
, core
, op_crates
runtime
の4つです。
また、deno コマンド自体には含まれませんが標準ライブラリの実装を含むディレクトリが std
。
開発に必要なプログラム類を含んでいるものは test_util
third_party
tools
の3つです。
ドキュメントや example に相当するものが docs
と test_plugin
の2つです。
以下では各ディレクトリの役割・含んでいる内容を紹介していきます。
Deno 本体
core/
Deno 本体は3レイヤーに分かれて実装されています。その最も根幹部分が core です。
core に含まれるものは V8 自体を起動する機能や、V8 と Rust の間で Op という命令の単位を送受信する仕組みが含まれています。また、モジュールの解決の仕組みなども一部 core の中で実装されています。
core 単体はコマンドランツールとしての機能はなく、Rust のライブラリとして上記のような機能を提供する、という形になっています。
runtime/
Deno 本体の3レイヤーのうち中間に位置するのがこの runtime/ (とそのプラグイン化された部分としての op_crates/) です。
このディレクトリは JS 実行環境としての各種機能を含んでいます。このレイヤーも CLI ツールとしてのエントリポイントは持っておらず Rust のライブラリとして、Deno ランタイムを起動できる機能を提供する形になっています。
この runtime Crate を Rust のライブラリとして組み込むことで、Deno 互換の API を持った独自のランタイムを構築しやすくなっています。
runtime/js
Deno ランタイムの JS 実装が置かれているディレクトリです。Deno API の JS 実装や、Web 互換 API の JS 実装がこのディレクトリ以下に含まれます。かつてはこれらは TS で実装されていましたが、ビルド時間が遅いなどの理由によって、最近 JS で書き換えられました。バンドル方法も import ではなく、concat で1ファイルに結合する原始的な形式になっています。
runtime/ops
Op の Rust 側の実装が含まれているディレクトリです。Op というのは、Deno の JS ランタイム API が Rust 側のランタイムに要求を出すための仕組みです (ファイルアクセス・ネットワークアクセス・環境変数アクセスなどあらゆる PC 上のリソースアクセスが Op として表現されます)。このディレクトリ以下で各種の Op を Deno のコアに対して登録しています。
なお、現在はまだ、ほとんどの Op がこのディレクトリ内で実装されていますが、将来的には各 Op を独立した Op の Crate として分離する予定があり、現在は一部の Web API 系だけが独立して、後述の op_crates/ 以下に移動されています。
op_crates/fetch/
Fetch API (と、その Op の op_fetch) の実装を含んでいるディレクトリです。
op_crates/crypto/
Web Crypto API (window.crypto.getRandomValues とその Op の op_get_random_values) の実装を含んだディレクトリです。
op_crates/web/
上記以外の Web API とその関連 Op の実装を含んでいるディレクトリです。
cli/
コマンドラインツールとしての Deno の実装が含まれています。Deno の各種サブコマンド (deno lint
, deno fmt
, etc) の実装や、TypeScript をコンパイルする機能などはこのディレクトリに含まれます。
cli/ 以下は更に役割によって以下のように分割されています。
cli/dts
Deno の API の TS としての型定義が含まれています。現在 Deno の API はすべて TS ではなく、JS で実装されており、原始的なファイル名順の concat でビルドされています。したがって、実装には型定義は含まれていないため、実装と独立して d.ts ファイルを手動で管理しています。
cli/lsp
Deno Language Server (deno lsp
コマンド) の実装が含まれています。
cli/tests
Deno ランタイムのインテグレーションテストが配置されているディレクトリです。このディレクトリ直下のファイルでは、基本的には、Deno を CLI ツールとして起動して、その出力をテストするというタイプのテストが置かれています。インテグレーションテストは比較的実行に時間がかかるため、出来るだけ後述のユニットテストの中でテストすべきです。ユニットテストではテストできない特殊な挙動をインテグレーションテストでテストすべきとされています。
cli/tests/unit
Deno ランタイムの JS 実装のユニットテストが配置されているディレクトリです。大部分の Deno API はこのディレクトリ以下でテストされています。各テストでは、必要なパーミッションを宣言出来るような仕組みになっています。
cli/tsc
TypeScript コンパイラランライムに読み込ませる JS 実装が含まれています。このディレクトリは TS のソースコード全体をファイルとして含んでいます。メインの実装部分では TS コンパイラ API をカスタマイズして、Deno の都合に合わせた TS のコンパイルをする各種設定が含まれています。
標準モジュール
std/
Deno の標準モジュールの実装が置かれているディレクトリです。
Deno の標準モジュールは基本的にはすべて TypeScript で書かれています (一部例外的に wasm が使われている箇所などもあるようです)。標準モジュールのカバー範囲はかなり広く、圧縮アルゴリズム、各種ファイル形式のパーサ、ファイルアクセスユーティリティ類、日付関連ユーティリティ、Node.js 互換API、HTTP、WebSocket、WASI、etc などかなり広範な内容を含んでいます。Deno 自体は 1.0 安定版が一旦リリースされていますが、標準モジュールについてはまだ 1.0 はリリースされておらず、今後もこのディレクトリ以下はかなり大きい変更が入っていくことが予想されます。
また、最近では標準モジュールを安定化させるための WG が隔週で開催されています。
開発ツール類
third_party/
Deno の 3rd party 依存の全体を含んだサブモジュール ( https://github.com/denoland/deno_third_party ) のディレクトリです。
かつてはこのディレクトリには V8 全体、Rust の Crates、Python packages、Node modules、etc など膨大な量の依存ファイルがまとめて置かれていました。現在はリファクタリングが進んだ結果、ほとんどの依存ファイルは必要無くなり、一部のツール (deno_lint(rust)、dprint(rust)、wrk(c)、hyperfine(rust)) のバイナリファイルだけが置かれています。
tools/
開発ツール類を含むディレクトリです。リンターや、フォーマッターのラッパースクリプトが Deno で実装されています。これらのツール類はつい最近まで Python 2 で書かれていましたが、CI でも Deno を使おうという方針が決まり、全て Deno 自身で書き直されました。
test_util
テストに必要な各種ユーティリティを含んだディレクトリです。特に、ネットワークを介する各種挙動をテストするための特殊な fixture としての挙動を持った http server などがこのディレクトリ以下で実装されています。
ドキュメント/example 類
docs/
Deno の公式マニュアル ( https://deno.land/manual ) のソースコードが含まれています。ホームページ自体は別レポジトリ ( https://github.com/denoland/deno_website2 ) で、Next.js アプリとして実装されていて、この docs/ 以下にあるマークダウンファイルをマニュアルとして取り込んでいます。
test_plugin/
Deno の Native プラグインのサンプル実装が置いてあるディレクトリです。なお、Deno の Native Plugin 機能は、機能自体の削除が検討されているため、このディレクトリは近い将来無くなる可能性が高そうです。
まとめ
今日は Deno 本体レポジトリのディレクトリ構造と各ディレクトリの役割について紹介しました。