{
    "componentChunkName": "component---src-templates-blog-post-jsx",
    "path": "/post/code-reading-of-deno-boot-process/",
    "result": {"data":{"site":{"siteMetadata":{"title":"WEB EGG","author":"Leko - CTO at Yuimedi"}},"markdownRemark":{"id":"08e307ba-06e0-5108-b599-f3bcc5e64f90","excerpt":"Denoのコードを読んでみました。 Rust に入門したばかりで基礎知識が足らず四苦八苦していますが、Deno のプロセスが起動してから TypeScript のコードが実行されるまでの仕組みについて愚直に読んでみたメモです。 想定読者 Deno の内部挙動に興味がある Node.js、TypeScript、C…","html":"<p><a href=\"https://github.com/denoland/deno\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Deno</a>のコードを読んでみました。<br>\nRust に入門したばかりで基礎知識が足らず四苦八苦していますが、Deno のプロセスが起動してから TypeScript のコードが実行されるまでの仕組みについて愚直に読んでみたメモです。</p>\n<h2 id=\"想定読者\" style=\"position:relative;\"><a href=\"#%E6%83%B3%E5%AE%9A%E8%AA%AD%E8%80%85\" aria-label=\"想定読者 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>想定読者</h2>\n<ul>\n<li>Deno の内部挙動に興味がある</li>\n<li>Node.js、TypeScript、C++（と V8）のコードがドキュメントを参照しつつ読める</li>\n<li>Rust で Hello world したことある程度の経験がある</li>\n</ul>\n<h2 id=\"参考情報\" style=\"position:relative;\"><a href=\"#%E5%8F%82%E8%80%83%E6%83%85%E5%A0%B1\" aria-label=\"参考情報 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>参考情報</h2>\n<p>コア内部を理解するには非公式ガイド（以下ガイド）がとても参考になります。</p>\n<blockquote>\n<p>— <a href=\"https://denolib.gitbook.io/guide/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">A Guide to Deno Core - A Guide to Deno Core</a></p>\n</blockquote>\n<p>Deno のディレクトリ構成やレイヤー分けについては<a href=\"https://denolib.gitbook.io/guide/codebase-basics/repo-structure\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Repo Structure</a>と<a href=\"https://denolib.gitbook.io/guide/codebase-basics/infrastructure\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Infrastructure</a>を一読し、リポジトリの構造をざっくり把握してからコードを読み始めるとより捗ると思います。</p>\n<p>また、すでに<a href=\"https://twitter.com/mizchi\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">mizchi</a>さんが<a href=\"https://gist.github.com/mizchi/31e5628751330b624a0e8ada9e739b1e\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Deno のコードを読んだメモ</a>を上げてました。そちらもとても参考になりました。</p>\n<h2 id=\"deno-のビルドツール\" style=\"position:relative;\"><a href=\"#deno-%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%83%84%E3%83%BC%E3%83%AB\" aria-label=\"deno のビルドツール permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deno のビルドツール</h2>\n<p>まず Deno のビルドツールについて軽く触れます。<br>\nDeno では<a href=\"https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/README.md\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">gn</a>という Node.js でおなじみの <a href=\"https://gyp.gsrc.io\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">gyp</a> の次期バージョンをビルドツールに用いています。</p>\n<blockquote>\n<p>What is GN?\nGN is a meta-build system that generates NinjaBuild files. It’s meant to be faster and simpler than GYP. It outputs only Ninja build files.</p>\n<p>— <a href=\"https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/README.md\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">What is GN?</a></p>\n</blockquote>\n<p>コードを読む上でビルド設定のすべてを理解する必要はありませんが、これを読まないと次に実行されるコードがわからない、このコードがどこから出現したかわからないってことが結構あるので、必要に応じてビルド設定も併せて読むと読み進められると思います。</p>\n<h2 id=\"srcmainrs-の-main-関数のアウトライン\" style=\"position:relative;\"><a href=\"#srcmainrs-%E3%81%AE-main-%E9%96%A2%E6%95%B0%E3%81%AE%E3%82%A2%E3%82%A6%E3%83%88%E3%83%A9%E3%82%A4%E3%83%B3\" aria-label=\"srcmainrs の main 関数のアウトライン permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>src/main.rs の main 関数のアウトライン</h2>\n<p><code>deno</code>コマンドを実行したときに真っ先に実行されるファイルは<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/main.rs\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/main.rs</a>です。ビルドツールで<code>deno</code>コマンドを生成する際のエントリポイントとして<code>src/main.rs</code>が指定されています。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/BUILD.gn#L127-L129\">deno/BUILD.gn</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 127 to 129 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre style=\"counter-reset: linenumber 126\" class=\"language-python line-numbers\"><code class=\"language-python\">\nrust_executable<span class=\"token punctuation\">(</span><span class=\"token string\">\"deno\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  source_root <span class=\"token operator\">=</span> <span class=\"token string\">\"src/main.rs\"</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div></p>\n<p>main.rs の詳細に入る前に<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/main.rs#L62\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>main</code></a>関数のアウトラインを整理し、用語の補足をしてから次に進みます。またガイドの<a href=\"https://denolib.gitbook.io/guide/advanced/process-lifecycle#lifecycle-example\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Rust main() Entry Point</a>にも説明があるので併せてご覧ください。</p>\n<ol>\n<li>ロガーをセット</li>\n<li>コマンドライン引数をパース</li>\n<li><code>--help</code>オプションをチェックし、あればヘルプを表示して終了</li>\n<li>コマンドライン引数に応じてログレベルを設定</li>\n<li>コマンドライン引数をもとに<code>Arc&#x3C;IsolateState></code>インスタンスを生成</li>\n<li><code>snapshot::deno_snapshot</code>で V8 スナップショットを取得</li>\n<li>V8 スナップショットから V8 Isolate（以下 Isolate）インスタンスを生成</li>\n<li><code>tokio_util::init</code>で Tokio を初期化</li>\n<li>生成した Isolate で JS のコード<code>denoMain();</code>を評価する</li>\n<li>コマンドライン引数で与えられたファイルパスを評価する（もしくは REPL を起動）</li>\n<li>イベントループを開始</li>\n</ol>\n<p>という流れになっています。用語を補足してから詳細を読み進めます。すでに知ってる方は先へお進み下さい。</p>\n<p>ロガーや<code>--help</code>周りはコード量も少ないしシンプルなので解説は割愛します。またイベントループに関してはかなり長くなると判断したので本記事では割愛します。イベントループについてはガイドの<a href=\"https://denolib.gitbook.io/guide/advanced/process-lifecycle#isolate-event_loop\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">isolate.event_loop()</a>にて詳しく説明されているのでそちらを参照して下さい。</p>\n<h3 id=\"補足-isolate-とは\" style=\"position:relative;\"><a href=\"#%E8%A3%9C%E8%B6%B3-isolate-%E3%81%A8%E3%81%AF\" aria-label=\"補足 isolate とは permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>[補足] Isolate とは</h3>\n<p>Isolate は V8 が提供している API の１つです。<br>\nDeno にこれをラップした isolate.rs などがありますが、末端までコードを読むと結局は V8 の Isolate を操作しています。</p>\n<blockquote>\n<p>Isolate\nAn isolate is a concept of an instance in V8. In Blink, isolates and threads are in 1:1 relationship. One isolate is associated with the main thread. One isolate is associated with one worker thread. An exception is a compositor worker where one isolate is shared by multiple compositor workers.</p>\n<p>— <a href=\"https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Design of V8 bindings</a></p>\n</blockquote>\n<blockquote>\n<p>— <a href=\"https://www.publickey1.jp/blog/18/vmv8isolatecloudflareworkers.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">VM よりコンテナよりもさらに軽量な分離技術、V8 の Isolate を用いてサーバレスコンピューティングを提供する Cloudflare Workers － Publickey</a></p>\n</blockquote>\n<h3 id=\"補足-v8-スナップショットとは\" style=\"position:relative;\"><a href=\"#%E8%A3%9C%E8%B6%B3-v8-%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%81%A8%E3%81%AF\" aria-label=\"補足 v8 スナップショットとは permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>[補足] V8 スナップショットとは</h3>\n<p>V8 には生成された Isolate Context の状態をシリアライズしておき、それをデシリアライズして利用することでオーバーヘッドを削減し Isolate Context の生成を高速化する スナップショットの機能があります。</p>\n<p>Node.js でも V8 スナップショットを使用してプロセスの起動を高速化する RFC が<a href=\"https://github.com/nodejs/node/issues/17058\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#17058</a>にて議論されています。<br>\nその Issue のより詳細な資料<a href=\"https://docs.google.com/document/d/1YEIBdH7ocJfm6PWISKw03szNAgnstA2B3e8PZr_-Gp4/edit#\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Speeding up Node.js startup using V8 snapshot</a>によると V8 スナップショットを使うことで、プロセスの起動時間を最大で２桁倍高速化できる見立てがあるようです。</p>\n<blockquote>\n<p>「このタイプの callback 関数があるから、この Object を用意して、この値を設定して」とやっていくのは効率が良くありません。「一通り定義したらこれだけのメモリが必要で、こんなレイアウトになってるから」という感じにできないでしょうか？\nそこで我々は V8 が用意してくれていた Snapshot の機能を使って効率化することにしました。ちなみに純粋な V8 でも同様に Context を作る度に Math などの Built-in object を作るのが非効率ということで、この Snapshot 機能を作ったという背景があります。</p>\n<p>— <a href=\"https://qiita.com/peria/items/eb4e39b975fd0cb148c3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">V8 Context の作成を Snapshot を使って高速化した話 - Qiita</a></p>\n</blockquote>\n<h3 id=\"補足-arc-とは\" style=\"position:relative;\"><a href=\"#%E8%A3%9C%E8%B6%B3-arc-%E3%81%A8%E3%81%AF\" aria-label=\"補足 arc とは permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>[補足] Arc とは</h3>\n<p>Arc って名前から全くピンとこなかったのですが、Atomically Reference Counted の略だそうです。<br>\nAtomic がついてないシングルスレッド版の<a href=\"https://doc.rust-lang.org/std/rc/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">rc</a>という crate もあるようです。</p>\n<blockquote>\n<p>A thread-safe reference-counting pointer. ‘Arc’ stands for ‘Atomically Reference Counted’.</p>\n<p>— <a href=\"https://doc.rust-lang.org/std/sync/struct.Arc.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">std::sync::Arc - Rust</a></p>\n</blockquote>\n<blockquote>\n<p>スレッドをまたいで参照を共有するために、Rust は <code>Arc&#x3C;T></code> というラッパ型を提供しています。</p>\n<p>— <a href=\"https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/concurrency.html#sync\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">並行性</a></p>\n</blockquote>\n<h3 id=\"補足-tokio-とは\" style=\"position:relative;\"><a href=\"#%E8%A3%9C%E8%B6%B3-tokio-%E3%81%A8%E3%81%AF\" aria-label=\"補足 tokio とは permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>[補足] tokio とは</h3>\n<p>私もきちんと理解できていないので引用だけにとどめます。<br>\ntokio 周りは読み飛ばしてもコードの流れは追えます。どの処理で・どんな単位で並列化/多重化してるかについてしっかり読む場合は tokio と Futures の理解が必要になります。</p>\n<blockquote>\n<p>Tokio is an event-driven, non-blocking I/O platform for writing asynchronous applications with the Rust programming language.</p>\n<p>— <a href=\"https://github.com/tokio-rs/tokio\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">tokio-rs/tokio: A runtime for writing reliable, asynchronous, and slim applications with the Rust programming language.</a></p>\n</blockquote>\n<blockquote>\n<p>futures::{Future, Stream} で実装された非同期かつゼロコストなグリーンスレッドを使ってネットワークプログラミングするためのフレームワーク</p>\n<p>— <a href=\"https://raskr.hatenablog.com/entry/2018/07/16/214420\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Tokio と Future のチュートリアルとかのまとめ+α - かっこかり(仮)</a></p>\n</blockquote>\n<h2 id=\"コマンドライン引数のパース\" style=\"position:relative;\"><a href=\"#%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E5%BC%95%E6%95%B0%E3%81%AE%E3%83%91%E3%83%BC%E3%82%B9\" aria-label=\"コマンドライン引数のパース permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>コマンドライン引数のパース</h2>\n<p>それでは main のアウトラインに沿って詳細を読んでいきます。<br>\nまずコマンドライン引数のパース周りの処理は<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/flags.rs\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/flags.rs</a>にあります。<br>\nパース処理は、まず V8 用のオプションのパースから実行されます。<code>v8_set_flags</code>関数です。この関数で V8 用のオプションとそれ以外（Deno の引数）を分離し、V8 用の引数は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L103-L105\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/api.cc の<code>deno_set_v8_flags</code></a>に渡し、Deno 用の引数は後続の処理に引き継ぎます。<br>\n<code>libdeno::deno_set_v8_flags</code> が定義されているのは<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/libdeno/api.cc#L103-L105\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/api.cc</a>です。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/libdeno/api.cc#L103-L105\">deno/libdeno/api.cc</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 103 to 105 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre style=\"counter-reset: linenumber 102\" class=\"language-cpp line-numbers\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">deno_set_v8_flags</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span> argc<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span> argv<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  v8<span class=\"token double-colon punctuation\">::</span><span class=\"token class-name\">V8</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">SetFlagsFromCommandLine</span><span class=\"token punctuation\">(</span>argc<span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div></p>\n<p>C++で定義された関数を Rust から呼び出すための FFI の定義が<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/libdeno.rs#L129-L132\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/libdeno.rs</a>に書かれています。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/libdeno.rs#L129-L132\">deno/src/libdeno.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 129 to 132 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 128\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">extern</span> <span class=\"token string\">\"C\"</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">deno_init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">deno_v8_version</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token operator\">*</span><span class=\"token keyword\">const</span> c_char<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">deno_set_v8_flags</span><span class=\"token punctuation\">(</span>argc<span class=\"token punctuation\">:</span> <span class=\"token operator\">*</span><span class=\"token keyword\">mut</span> c_int<span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">:</span> <span class=\"token operator\">*</span><span class=\"token keyword\">mut</span> <span class=\"token operator\">*</span><span class=\"token keyword\">mut</span> c_char<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>V8 のオプションか否かを判定する方法は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/flags.rs#L301-L303\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">コメント</a>によると<code>libdeno::deno_set_v8_flags</code>内部で呼び出されている<code>v8::V8::SetFlagsFromCommandLine</code>の内部に書かれており、引数で渡したコマンドラインオプションのうち、V8 が解釈できたオプションだけ取り除かれるという破壊的操作になってるようですようです。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/flags.rs#L301-L303\">deno/src/flags.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 301 to 303 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 300\" class=\"language-rust line-numbers\"><code class=\"language-rust\">  <span class=\"token comment\">// deno_set_v8_flags(int* argc, char** argv) mutates argc and argv to remove</span>\n  <span class=\"token comment\">// flags that v8 understands.</span>\n  <span class=\"token comment\">// First parse core args, then convert to a vector of C strings.</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div></p>\n<p>V8 が解釈できなかった残りのオプションのパース処理は Rust の<a href=\"https://docs.rs/getopts/0.2.18/getopts/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">getopts</a>という crate をラップした独自関数を用いています getopts は予期しないオプションが渡されたときにエラー扱いになるのですが、そのエラーを自前でハンドルするためにラップした<code>set_recognized_flags</code>という関数を使用しています。“better solution welcome!”だそうです。なお Deno に指定可能なオプションは<code>set_flags</code>関数を読めばわかります。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/flags.rs#L62-L64\">deno/src/flags.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 62 to 64 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 61\" class=\"language-rust line-numbers\"><code class=\"language-rust\">  <span class=\"token comment\">// getopts doesn't allow parsing unknown options so we check them</span>\n  <span class=\"token comment\">// one-by-one and handle unrecognized ones manually</span>\n  <span class=\"token comment\">// better solution welcome!</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div></p>\n<h2 id=\"コマンドライン引数からarcisolatestateインスタンスを生成\" style=\"position:relative;\"><a href=\"#%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E5%BC%95%E6%95%B0%E3%81%8B%E3%82%89arcisolatestate%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%92%E7%94%9F%E6%88%90\" aria-label=\"コマンドライン引数からarcisolatestateインスタンスを生成 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>コマンドライン引数から<code>Arc&#x3C;IsolateState></code>インスタンスを生成</h2>\n<p><code>isolate::IsolateState::new</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L79-L94\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/isolate.rs</a>に定義されていますが、これ自体はただの構造体を初期化してるだけだったので詳細を割愛。</p>\n<h2 id=\"v8-スナップショットを取得\" style=\"position:relative;\"><a href=\"#v8-%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%82%92%E5%8F%96%E5%BE%97\" aria-label=\"v8 スナップショットを取得 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>V8 スナップショットを取得</h2>\n<p><code>snapshot::deno_snapshot</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/snapshot.rs#L4-L14\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/snapshot.rs</a>に定義されています。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/snapshot.rs#L4-L14\">deno/src/snapshot.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 4 to 14 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 3\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">deno_snapshot</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> deno_buf <span class=\"token punctuation\">{</span>\n  <span class=\"token attribute attr-name\">#[cfg(not(feature = <span class=\"token string\">\"check-only\"</span>))]</span>\n  <span class=\"token keyword\">let</span> data <span class=\"token operator\">=</span>\n    <span class=\"token macro property\">include_bytes!</span><span class=\"token punctuation\">(</span><span class=\"token macro property\">concat!</span><span class=\"token punctuation\">(</span><span class=\"token macro property\">env!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"GN_OUT_DIR\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"/gen/snapshot_deno.bin\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// The snapshot blob is not available when the Rust Language Server runs</span>\n  <span class=\"token comment\">// 'cargo check'.</span>\n  <span class=\"token attribute attr-name\">#[cfg(feature = <span class=\"token string\">\"check-only\"</span>)]</span>\n  <span class=\"token keyword\">let</span> data <span class=\"token operator\">=</span> <span class=\"token macro property\">vec!</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">unsafe</span> <span class=\"token punctuation\">{</span> <span class=\"token namespace\">deno_buf<span class=\"token punctuation\">::</span></span><span class=\"token function\">from_raw_parts</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span><span class=\"token function\">as_ptr</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> data<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p><code>{GN_OUT_DIR}/gen/snapshot_deno.bin</code>というファイルから V8 スナップショットを取得しています。このファイルは gn でビルドする時に生成されているようです。環境変数<code>GN_OUT_DIR</code>の値はデバッグビルドした環境では<code>target/debug</code>になってました。</p>\n<p>スナップショットを生成するビルドタスクは\n<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/BUILD.gn#L233\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">BUILD.gn の<code>snapshot(\"snapshot_deno\")</code></a>に定義があります。<code>snapshot</code>というテンプレートは<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/deno.gni#L12\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/deno.gni</a>に定義されていました。<code>.gni</code>は GN のビルド設定を別ファイルに定義して import できるようにしたものだそうです。</p>\n<blockquote>\n<p>You can import .gni files into the current scope with the import function.</p>\n<p>— <a href=\"https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/docs/language.md#imports\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">GN Language and Operation</a></p>\n</blockquote>\n<p><code>libdeno/deno.gni</code>の中に<code>tool = \"//libdeno:snapshot_creator\"</code>と指定があるように、V8 スナップショットを生成するファイルは<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/snapshot_creator.cc#L13\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/snapshot_create.cc</a>です。main 関数に渡される引数は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/deno.gni#L22-L30\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ビルド定義</a>を読んでみると第一引数が出力先（<code>gen/snapshot_deno.bin</code>）のパス、第二引数が スナップショットを取りたい js（<code>bundle/main.js</code>）のパスになっていました。\nmain 関数の内部処理としては、<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L116\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>deno_execute</code></a>で与えられた js（<code>bundle/main.js</code>）を実行した結果の Isolate Context の スナップショットを<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L80\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>deno_get_snapshot</code></a>で取得し、指定されたパス（<code>gen/snapshot_deno.bin</code>）に保存するという感じです。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/deno.gni#L22-L30\">deno/libdeno/deno.gni</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 22 to 30 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre style=\"counter-reset: linenumber 21\" class=\"language-python line-numbers\"><code class=\"language-python\">    inputs <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n      invoker<span class=\"token punctuation\">.</span>source_root<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">]</span>\n\n    outputs <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n      snapshot_out_bin<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">]</span>\n    args <span class=\"token operator\">=</span> rebase_path<span class=\"token punctuation\">(</span>outputs<span class=\"token punctuation\">,</span> root_build_dir<span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span>\n           rebase_path<span class=\"token punctuation\">(</span>inputs<span class=\"token punctuation\">,</span> root_build_dir<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>なお前触れなく登場した<code>bundle/main.js</code>とは<a href=\"https://rollupjs.org/guide/en\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">rollup</a>で生成された Deno の TypeScript のコード bundle した生成物です。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ head -n5 target/debug/gen/bundle/main.js\nvar denoMain = (function () {\n  'use strict';\n\n  var runner = /*#__PURE__*/Object.freeze({\n    get Runner () { return Runner; }</code></pre></div>\n<p>ここからさらにビルド周りを深追いしていくと submodule になっている<a href=\"https://github.com/denoland/chromium_build/blob/1e3840b6d9c3fd3dc7be4fc2c1a2de7798d63df6/compiled_action.gni#L75\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">denoland/chromium_build</a>などの別リポジトリにたどり着くのですが、ビルドプロセスを深堀りしすぎると本筋から逸脱するのでこれぐらいにします。</p>\n<h2 id=\"v8-スナップショットから-isolate-インスタンスを生成\" style=\"position:relative;\"><a href=\"#v8-%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%81%8B%E3%82%89-isolate-%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%92%E7%94%9F%E6%88%90\" aria-label=\"v8 スナップショットから isolate インスタンスを生成 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>V8 スナップショットから Isolate インスタンスを生成</h2>\n<p><code>isolate::Isolate::new</code>も<code>IsolateState</code>と同じく<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L162\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>src/isolate.rs</code></a>に定義されています。<br>\n渡している引数は上の行で生成した V8 snapshot、２つ上の行で生成した IsolateState、<code>opt::dispatch</code>の３つです。<code>opt::dispatch</code>に関してはひとまずこちらを参照。後々<code>denoMain</code>関数を実行するあたりでまた出てきます。</p>\n<blockquote>\n<p>第三引数の dispatch ってなんだ、と思ったらコメントに色々書いてある。<br>\njs からの来る諸々を Rust で捌いてる部分っぽく見える。</p>\n<p>— <a href=\"https://gist.github.com/mizchi/31e5628751330b624a0e8ada9e739b1e\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">deno_code_reading.md</a></p>\n</blockquote>\n<p><code>isolate::Isolate::new</code>のアウトラインは、</p>\n<ol>\n<li>（プロセス中で１回だけ）<code>libdeno::deno_init()</code>で初期化</li>\n<li>引数で受け取った スナップショットを使って<code>libdeno::deno_config</code>のインスタンスを生成</li>\n<li>生成した<code>deno_config</code>を<code>deno_new</code>に渡して<code>libdeno_isolate</code>のインスタンスを生成</li>\n<li>並列処理のメッセージングに使うチャネルを生成</li>\n<li>Isolate インスタンス作って返却</li>\n</ol>\n<p>という感じになっています。</p>\n<p><a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L93\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>libdeno::deno_init()</code></a>は V8 の初期化をしています。</p>\n<p><code>deno_new</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L40\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/api.cc</a>に定義されています。<br>\n先程の<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/snapshot_creator.cc#L26-L27\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">スナップショットを生成する処理</a>でも登場しており、そのときは<code>will_snapshot</code>が 1、<code>load_snapshot</code>が<code>deno::empty_buf</code>になっていました。今回は<code>deno_new</code>に<code>will_snapshot</code>を 0、<code>load_snapshot</code>に生成された スナップショットを指定しています。それぞれの値の違いによる処理の分岐はこのあたりを見れば明らかかと思います。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/libdeno/api.cc#L40-L51\">deno/libdeno/api.cc</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 40 to 51 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre style=\"counter-reset: linenumber 39\" class=\"language-cpp line-numbers\"><code class=\"language-cpp\">Deno<span class=\"token operator\">*</span> <span class=\"token function\">deno_new</span><span class=\"token punctuation\">(</span>deno_config config<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>config<span class=\"token punctuation\">.</span>will_snapshot<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">deno_new_snapshotter</span><span class=\"token punctuation\">(</span>config<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  deno<span class=\"token double-colon punctuation\">::</span>DenoIsolate<span class=\"token operator\">*</span> d <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> deno<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">DenoIsolate</span><span class=\"token punctuation\">(</span>config<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  v8<span class=\"token double-colon punctuation\">::</span>Isolate<span class=\"token double-colon punctuation\">::</span>CreateParams params<span class=\"token punctuation\">;</span>\n  params<span class=\"token punctuation\">.</span>array_buffer_allocator <span class=\"token operator\">=</span> d<span class=\"token operator\">-></span>array_buffer_allocator_<span class=\"token punctuation\">;</span>\n  params<span class=\"token punctuation\">.</span>external_references <span class=\"token operator\">=</span> deno<span class=\"token double-colon punctuation\">::</span>external_references<span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>config<span class=\"token punctuation\">.</span>load_snapshot<span class=\"token punctuation\">.</span>data_ptr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    params<span class=\"token punctuation\">.</span>snapshot_blob <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>d<span class=\"token operator\">-></span>snapshot_<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>スナップショットを用いて<code>V8::Isolate</code>のインスタンスを作ってスコープ設定して…とわちゃわちゃやってますが、このあたりは V8 自体の説明になってしまうので割愛します。この記事とガイドにて丁寧な解説されているので理解の助けになると思います。</p>\n<blockquote>\n<p>— <a href=\"https://qiita.com/komukomo/items/316afadd04f95808f338\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">V8 の基本的な API を学ぶ - Qiita</a></p>\n</blockquote>\n<blockquote>\n<p>There are 2 important functions/constructors used in deno_new that might not be immediately clear: DenoIsolate and InitializeContext. It turns out DenoIsolate serves more or less as a collection of Isolate information. Instead, InitializeContext is the more interesting one.</p>\n<p>— <a href=\"https://denolib.gitbook.io/guide/advanced/interaction-with-v8\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Interaction with V8 - A Guide to Deno Core</a></p>\n</blockquote>\n<h2 id=\"生成した-isolate-でdenomain関数を実行\" style=\"position:relative;\"><a href=\"#%E7%94%9F%E6%88%90%E3%81%97%E3%81%9F-isolate-%E3%81%A7denomain%E9%96%A2%E6%95%B0%E3%82%92%E5%AE%9F%E8%A1%8C\" aria-label=\"生成した isolate でdenomain関数を実行 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>生成した Isolate で<code>denoMain</code>関数を実行</h2>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/main.rs#L89-L92\">deno/src/main.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 89 to 92 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 88\" class=\"language-rust line-numbers\"><code class=\"language-rust\">    <span class=\"token comment\">// Setup runtime.</span>\n    isolate\n      <span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"denoMain();\"</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">unwrap_or_else</span><span class=\"token punctuation\">(</span>print_err_and_exit<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>ここですね。<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L227-L254\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>isolate.execute</code></a>自体はごくシンプルで、内部で<code>ibdeno::deno_execute</code>を読んでるだけです。</p>\n<blockquote>\n<p>CString って C にわたす FFI 呼ぶときによく見るやつだ。 実質 <code>libdeno::deno_execute()</code> へのファサードになっている。</p>\n<p>— <a href=\"https://gist.github.com/mizchi/31e5628751330b624a0e8ada9e739b1e\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">deno_code_reading.md</a></p>\n</blockquote>\n<blockquote>\n<p>The only interesting function we care in this section is libdeno::deno_execute. We can find its actual definition in libdeno/api.cc again:</p>\n<p>— <a href=\"https://denolib.gitbook.io/guide/advanced/interaction-with-v8#executing-code-on-v8\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Interaction with V8 - A Guide to Deno Core</a></p>\n</blockquote>\n<p><a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L116-L127\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>deno_execute</code></a>は スナップショット作るところで１度登場していますが、そこでは読み飛ばしたので詳しく読んでみます。V8 Context を作って<code>deno::Execute</code>に渡してます。</p>\n<p><code>deno::Execute</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L636\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/binding.cc</a>に定義されています。<br>\nおおまかな流れとしては渡された文字列を<code>v8::Script::Compile</code>でコードをコンパイルし、エラーがなければ<code>Local&#x3C;Script>->Run(context)</code>でコードを実行して、エラーチェックして終わりです。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L636-L667\">deno/libdeno/binding.cc</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 636 to 667 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre style=\"counter-reset: linenumber 635\" class=\"language-cpp line-numbers\"><code class=\"language-cpp\"><span class=\"token keyword\">bool</span> <span class=\"token function\">Execute</span><span class=\"token punctuation\">(</span>v8<span class=\"token double-colon punctuation\">::</span>Local<span class=\"token operator\">&lt;</span>v8<span class=\"token double-colon punctuation\">::</span>Context<span class=\"token operator\">></span> context<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span><span class=\"token operator\">*</span> js_filename<span class=\"token punctuation\">,</span>\n             <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span><span class=\"token operator\">*</span> js_source<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">auto</span><span class=\"token operator\">*</span> isolate <span class=\"token operator\">=</span> context<span class=\"token operator\">-></span><span class=\"token function\">GetIsolate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  v8<span class=\"token double-colon punctuation\">::</span>Isolate<span class=\"token double-colon punctuation\">::</span>Scope <span class=\"token function\">isolate_scope</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  v8<span class=\"token double-colon punctuation\">::</span>HandleScope <span class=\"token function\">handle_scope</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  v8<span class=\"token double-colon punctuation\">::</span>Context<span class=\"token double-colon punctuation\">::</span>Scope <span class=\"token function\">context_scope</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">auto</span> source <span class=\"token operator\">=</span> <span class=\"token function\">v8_str</span><span class=\"token punctuation\">(</span>js_source<span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">auto</span> name <span class=\"token operator\">=</span> <span class=\"token function\">v8_str</span><span class=\"token punctuation\">(</span>js_filename<span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  v8<span class=\"token double-colon punctuation\">::</span>TryCatch <span class=\"token function\">try_catch</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  v8<span class=\"token double-colon punctuation\">::</span>ScriptOrigin <span class=\"token function\">origin</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">auto</span> script <span class=\"token operator\">=</span> v8<span class=\"token double-colon punctuation\">::</span><span class=\"token class-name\">Script</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">Compile</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> source<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>origin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>script<span class=\"token punctuation\">.</span><span class=\"token function\">IsEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">DCHECK</span><span class=\"token punctuation\">(</span>try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">HasCaught</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">HandleException</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">Exception</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">auto</span> result <span class=\"token operator\">=</span> script<span class=\"token punctuation\">.</span><span class=\"token function\">ToLocalChecked</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-></span><span class=\"token function\">Run</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span><span class=\"token function\">IsEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">DCHECK</span><span class=\"token punctuation\">(</span>try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">HasCaught</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">HandleException</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">Exception</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>まとめると、<code>isolate.execute(\"denoMain();\")</code>は<code>denoMain();</code>という文字列（JavaScript のコード）を V8 でコンパイルして実行しています。<br>\nいきなり<code>denoMain</code>関数を呼び出してますが<code>denoMain</code>とはどこから来たのでしょうか。これまでのコードでは denoMain 関数を定義するようなコードは登場しませんでした。おそらく V8 スナップショットから復元されています。<br>\nあらかじめ<code>denoMain</code>の関数定義を含んだ bundle/main.js を実行した結果をスナップショットとして保存し、それを使って Isolate を復元しているので<code>denoMain</code>関数が呼べるようになっています。</p>\n<blockquote>\n<p>前触れなく登場している<code>bundle/main.js</code>とは、js の bundler の１つである<a href=\"https://rollupjs.org/guide/en\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">rollup</a>で生成された<code>denoMain</code>関数を含む deno の js レイヤのコードです。</p>\n</blockquote>\n<p>引用したこのあたりです。demoMain 関数を呼び出せる仕組みがわかったので denoMain について詳しく読んでみます。</p>\n<h2 id=\"demomain-関数\" style=\"position:relative;\"><a href=\"#demomain-%E9%96%A2%E6%95%B0\" aria-label=\"demomain 関数 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>demoMain 関数</h2>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/js/main.ts#L59\">deno/js/main.ts</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 59 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre style=\"counter-reset: linenumber 58\" class=\"language-typescript line-numbers\"><code class=\"language-typescript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">denoMain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div></p>\n<blockquote>\n<p>要はここまでやって v8 が起動していることがわかった。じゃあどういうスクリプトが起動しているのか。</p>\n<p>— <a href=\"https://gist.github.com/mizchi/31e5628751330b624a0e8ada9e739b1e\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">deno_code_reading.md</a></p>\n</blockquote>\n<p>やっと Deno の TypeScript のレイヤにたどり着けました。といっても実際には rollup で bundle された JavaScript が実行されており TypeScript を直接実行しているわけではありません。</p>\n<p><code>denoMain</code>関数が定義されている<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/js/main.ts#L59\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">js/main.ts</a>は大きく分けて３パートに分かれています。</p>\n<ol>\n<li>denoMain</li>\n<li>sendStart</li>\n<li>compilerMain</li>\n</ol>\n<p><code>denoMain</code>は（コマンドライン）引数を処理して、<code>sendStart</code>をコールするなどの然るべき初期化を行います。<br>\n<code>sendStart</code>は<code>sendSync</code>という関数を用いて js レイヤの初期化が開始したことを C++レイヤへ通知しています。<br>\n<code>compilerMain</code>はここでは呼び出されていません。関数定義だけして window オブジェクトのプロパティにセットしています。この関数は後々 ts をコンパイルするところで再び登場します。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/js/main.ts#L60\">deno/js/main.ts</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 60 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre style=\"counter-reset: linenumber 59\" class=\"language-typescript line-numbers\"><code class=\"language-typescript\">  libdeno<span class=\"token punctuation\">.</span><span class=\"token function\">recv</span><span class=\"token punctuation\">(</span>handleAsyncMsgFromRust<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div></p>\n<p>denoMain 関数の冒頭にある<code>libdeno.recv</code>と<code>handleAsyncMsgFromRust</code>は、イベントリスナとイベントハンドラのようなものです。</p>\n<h3 id=\"補足-libdenoオブジェクト\" style=\"position:relative;\"><a href=\"#%E8%A3%9C%E8%B6%B3-libdeno%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88\" aria-label=\"補足 libdenoオブジェクト permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>[補足] <code>libdeno</code>オブジェクト</h3>\n<blockquote>\n<p>First, we tell libdeno, which is the exposed API from the middle-end, that whenever there is a message sent from the Rust side, please forward the buffer to a function called handleAsyncMsgFromRust. Then, a Start message is sent to Rust side, signaling that we are starting and receiving information including the current working directory, or cwd. We then decide whether the user is running a script, or using the REPL. If we have an input file name, Deno would then try to let the runner, which contains the TypeScript compiler, to try running the file (going deep into its definition, you’ll eventually find a secret eval/globalEval called somewhere). denoMain only exits when the runner finish running the file.</p>\n<p>— <a href=\"https://denolib.gitbook.io/guide/advanced/process-lifecycle#denomain\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Process Lifecycle - A Guide to Deno Core</a></p>\n</blockquote>\n<p>denoMain の中に<code>libdeno</code>という名前空間的なオブジェクトが登場しますが、このオブジェクトの定義は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/js/libdeno.ts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">js/libdeno.ts</a>には存在しません。どこかで事前に作られています。<br>\nlibdeno オブジェクトは<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L65-L69\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>libdeno/api.cc</code>の<code>deno_new</code>関数の内部処理</a>で読み飛ばした<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L669\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>InitializeContext</code></a>にて C++から V8 を直接操作して生成されています。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L675-L676\">deno/libdeno/binding.cc</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 675 to 676 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre style=\"counter-reset: linenumber 674\" class=\"language-cpp line-numbers\"><code class=\"language-cpp\">  <span class=\"token keyword\">auto</span> deno_val <span class=\"token operator\">=</span> v8<span class=\"token double-colon punctuation\">::</span><span class=\"token class-name\">Object</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">New</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">CHECK</span><span class=\"token punctuation\">(</span>global<span class=\"token operator\">-></span><span class=\"token function\">Set</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> deno<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">v8_str</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"libdeno\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> deno_val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">FromJust</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span></span></pre></div></p>\n<p>これで<code>libdeno</code>という空オブジェクトを作成し、その中に<code>print</code>, <code>recv</code>, <code>send</code>メソッドの実装をセットしています。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L678-L688\">deno/libdeno/binding.cc</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 678 to 688 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre style=\"counter-reset: linenumber 677\" class=\"language-cpp line-numbers\"><code class=\"language-cpp\">  <span class=\"token keyword\">auto</span> print_tmpl <span class=\"token operator\">=</span> v8<span class=\"token double-colon punctuation\">::</span><span class=\"token class-name\">FunctionTemplate</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">New</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">,</span> Print<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">auto</span> print_val <span class=\"token operator\">=</span> print_tmpl<span class=\"token operator\">-></span><span class=\"token function\">GetFunction</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ToLocalChecked</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">CHECK</span><span class=\"token punctuation\">(</span>deno_val<span class=\"token operator\">-></span><span class=\"token function\">Set</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> deno<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">v8_str</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"print\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> print_val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">FromJust</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">auto</span> recv_tmpl <span class=\"token operator\">=</span> v8<span class=\"token double-colon punctuation\">::</span><span class=\"token class-name\">FunctionTemplate</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">New</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">,</span> Recv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">auto</span> recv_val <span class=\"token operator\">=</span> recv_tmpl<span class=\"token operator\">-></span><span class=\"token function\">GetFunction</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ToLocalChecked</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">CHECK</span><span class=\"token punctuation\">(</span>deno_val<span class=\"token operator\">-></span><span class=\"token function\">Set</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> deno<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">v8_str</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"recv\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> recv_val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">FromJust</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">auto</span> send_tmpl <span class=\"token operator\">=</span> v8<span class=\"token double-colon punctuation\">::</span><span class=\"token class-name\">FunctionTemplate</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">New</span><span class=\"token punctuation\">(</span>isolate<span class=\"token punctuation\">,</span> Send<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">auto</span> send_val <span class=\"token operator\">=</span> send_tmpl<span class=\"token operator\">-></span><span class=\"token function\">GetFunction</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ToLocalChecked</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">CHECK</span><span class=\"token punctuation\">(</span>deno_val<span class=\"token operator\">-></span><span class=\"token function\">Set</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> deno<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">v8_str</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"send\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> send_val<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">FromJust</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>見ての通りこの３つの実装は C++で定義されており、V8 を操作して C++の関数ポインタを js 側に露出しています。<br>\n<code>print</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L255\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ここ</a>で定義されており、ざっくりまとめると<code>STDOUT</code>もしくは<code>STDERR</code>のどちらかに渡された引数を fwrite している。要は printf 的なものです。<br>\n<code>recv</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L330\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ここ</a>に定義されており、ざっくりまとめると渡された引数を関数としてキャストし、DenoIsolate の<code>recv_</code>プロパティにコールバック関数としてセットしています。<br>\n<code>send</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L349\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ここ</a>に定義されています。<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L174\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>src/isolate.rs</code>の中で<code>deno_new</code>関数の中で渡している<code>deno_config</code>の<code>recv_cb</code></a>が<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/internal.h#L22\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DenoIsolate</a>に渡っており、結果的に<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L425\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">pre_dispatch</a>という Rust の関数が呼び出されます。<br>\nという C++（Rust）レイヤとやりとりするための<code>libdeno</code>オブジェクトが定義されていました。</p>\n<p>Send に関してはガイドの説明も併せて参照してください。</p>\n<blockquote>\n<p>The Send function get args and invoke the recv<em>cb</em> . Notice that the recv<em>cb</em> is defined in the Rust code.</p>\n<p>— <a href=\"https://denolib.gitbook.io/guide/advanced/under-the-call-site-hood#c-converter\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Under the call site’s hood - A Guide to Deno Core</a></p>\n</blockquote>\n<h2 id=\"ファイルパスが与えられていたらそれをモジュールとして実行\" style=\"position:relative;\"><a href=\"#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%91%E3%82%B9%E3%81%8C%E4%B8%8E%E3%81%88%E3%82%89%E3%82%8C%E3%81%A6%E3%81%84%E3%81%9F%E3%82%89%E3%81%9D%E3%82%8C%E3%82%92%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%A8%E3%81%97%E3%81%A6%E5%AE%9F%E8%A1%8C\" aria-label=\"ファイルパスが与えられていたらそれをモジュールとして実行 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>（ファイルパスが与えられていたら）それをモジュールとして実行</h2>\n<p><code>denoMain</code>が実行され、Deno ランタイムの準備が整いました。<br>\n再び Rust の main 関数に話題を戻し、次はファイルパスがコマンドライン引数として与えられてるとき<code>isolate.execute_mod</code>が呼び出されるあたりを読みます。<br>\nこれまでも FFI で C++, Rust, js と複数レイヤをまたぐコードが多かったですが、ここから先も複雑かつ長いので、休憩しつつ読まれるといいと思います。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/main.rs#L94-L100\">deno/src/main.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 94 to 100 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 93\" class=\"language-rust line-numbers\"><code class=\"language-rust\">    <span class=\"token comment\">// Execute input file.</span>\n    <span class=\"token keyword\">if</span> isolate<span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>argv<span class=\"token punctuation\">.</span><span class=\"token function\">len</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">1</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">let</span> input_filename <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>isolate<span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>argv<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n      isolate\n        <span class=\"token punctuation\">.</span><span class=\"token function\">execute_mod</span><span class=\"token punctuation\">(</span>input_filename<span class=\"token punctuation\">,</span> should_prefetch<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span><span class=\"token function\">unwrap_or_else</span><span class=\"token punctuation\">(</span>print_err_and_exit<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p><code>isolate.execute_mod</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L256\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/isolate.rs</a>に定義されています。<br>\n<code>isolate.execute</code>と同じ要領で<code>deno_execute(filename, ファイルの中身)</code>と実行するのかと思いましたが、違いました。内部で呼び出されている<code>code_fetch_and_maybe_compile</code>という関数と<code>libdeno::deno_execute_mod</code>が気になります。まず<code>code_fetch_and_maybe_compile</code>から読んでみます。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/isolate.rs#L256-L286\">deno/src/isolate.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 256 to 286 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 255\" class=\"language-rust line-numbers\"><code class=\"language-rust\">  <span class=\"token comment\">/// Executes the provided JavaScript module.</span>\n  <span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">execute_mod</span><span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&amp;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">,</span>\n    js_filename<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n    is_prefetch<span class=\"token punctuation\">:</span> <span class=\"token keyword\">bool</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">JSError</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> out <span class=\"token operator\">=</span>\n      <span class=\"token function\">code_fetch_and_maybe_compile</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">,</span> js_filename<span class=\"token punctuation\">,</span> <span class=\"token string\">\".\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">let</span> filename <span class=\"token operator\">=</span> <span class=\"token class-name\">CString</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span>out<span class=\"token punctuation\">.</span>filename<span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">let</span> filename_ptr <span class=\"token operator\">=</span> filename<span class=\"token punctuation\">.</span><span class=\"token function\">as_ptr</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> <span class=\"token operator\">*</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">i8</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">let</span> js_source <span class=\"token operator\">=</span> <span class=\"token class-name\">CString</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">js_source</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">let</span> js_source <span class=\"token operator\">=</span> <span class=\"token class-name\">CString</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span>js_source<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">let</span> js_source_ptr <span class=\"token operator\">=</span> js_source<span class=\"token punctuation\">.</span><span class=\"token function\">as_ptr</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> <span class=\"token operator\">*</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">i8</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">let</span> r <span class=\"token operator\">=</span> <span class=\"token keyword\">unsafe</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token namespace\">libdeno<span class=\"token punctuation\">::</span></span><span class=\"token function\">deno_execute_mod</span><span class=\"token punctuation\">(</span>\n        <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>libdeno_isolate<span class=\"token punctuation\">,</span>\n        <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span><span class=\"token function\">as_raw_ptr</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        filename_ptr<span class=\"token punctuation\">,</span>\n        js_source_ptr<span class=\"token punctuation\">,</span>\n        <span class=\"token keyword\">if</span> is_prefetch <span class=\"token punctuation\">{</span> <span class=\"token number\">1</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> r <span class=\"token operator\">==</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">let</span> js_error <span class=\"token operator\">=</span> <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span><span class=\"token function\">last_exception</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">return</span> <span class=\"token class-name\">Err</span><span class=\"token punctuation\">(</span>js_error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p><code>code_fetch_and_maybe_compile</code>は<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/isolate.rs#L375\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/isolate.rs</a>に定義されています。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/isolate.rs#L375-L380\">deno/src/isolate.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 375 to 380 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/f9b167deb07a650590b7f1eef8fe86bf9e22d211\">f9b167d</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 374\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">code_fetch_and_maybe_compile</span><span class=\"token punctuation\">(</span>\n  state<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">Arc</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">IsolateState</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span>\n  specifier<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n  referrer<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">CodeFetchOutput</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">DenoError</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> out <span class=\"token operator\">=</span> state<span class=\"token punctuation\">.</span>dir<span class=\"token punctuation\">.</span><span class=\"token function\">code_fetch</span><span class=\"token punctuation\">(</span>specifier<span class=\"token punctuation\">,</span> referrer<span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>１行目の<code>state.dir.code_fetch</code>は<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/isolate.rs#L70\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">型定義</a>を読んでみると<code>deno_dir::DenoDir</code>というメソッドです。<a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/deno_dir.rs#L276\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">src/deno_dir.rs</a>に定義されています。<code>DenoDir#code_fetch</code>のアウトラインとしては、</p>\n<ol>\n<li><a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/deno_dir.rs#L360\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>resolve_module</code></a>でモジュールのファイルパス（か URL）を解決</li>\n<li><a href=\"https://github.com/denoland/deno/blob/f9b167deb07a650590b7f1eef8fe86bf9e22d211/src/deno_dir.rs#L228\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>get_source_code</code></a>で<code>/https?/</code>で始まるなら<code>fetch_remote_source</code>、それ以外なら<code>fetch_local_source</code>を使用して TypeScript のコードを取得</li>\n<li><code>filter_shebang</code>で shebang を取り除いて</li>\n<li><code>load_cache</code>でコンパイル後の JavaScript とその Source Map を手に入れる</li>\n</ol>\n<p>となっております。<br>\nここから先<code>resolve_module</code>やそれ以外の箇所で<code>specifier</code>、<code>referrer</code>という変数がよく登場します。<code>specifier</code>はモジュールの名前・パス解決の処理全般で、<code>import from</code>に記載した文字列（もしくはコマンドライン引数で与えたファイルパス）を現しています。<code>referrer</code>は import が記載されているファイルの絶対パス（もしくは URL）と念頭に置いておくとコードが読みやすいと思います。<br>\n<code>get_source_code</code>にてローカルかリモートかにかかわらず返却されている<code>CodeFetchOutput</code>型の構造は以下のとおりです。</p>\n<ul>\n<li><code>module_name</code>: specifier</li>\n<li><code>filename</code>: 解決できたファイル名（もしくは URL）</li>\n<li><code>media_type</code>: <code>msg::MediaType::TypeScript</code>、<code>msg::MediaType::JavaScript</code>、<code>msg::MediaType::Json</code>、<code>msg::MediaType::Unknown</code>のいずれか</li>\n<li><code>source_code</code>: ファイル内容</li>\n<li><code>maybe_output_code</code>: （<code>fetch_local_source</code>の場合常に None）</li>\n<li><code>maybe_source_map</code>: （<code>fetch_local_source</code>の場合常に None）</li>\n</ul>\n<p>ローカルのファイルパスを解決する<code>fetch_local_source</code>の面白い挙動としては、<code>ファイル名.mime</code>というファイルがもし置かれていれば、そのメディアタイプとして解釈する挙動になっています。ローカルファイルでこれをわざわざやる必要は無さそうですが、リモートのファイルとを取ってくるときに Content-Type ヘッダの値を格納しておくという使い方をしています。<br>\nなお<code>.mime</code>ファイルがなければファイルの拡張子ごとにあらかじめ定義されているタイプとして解釈します。例えば<code>.ts</code>は TypeScript として解釈します。</p>\n<p>リモートの URL を解決する<code>fetch_remote_source</code>ではソースを HTTP GET してきて、URL 末尾の拡張子に対応するメディアタイプと、レスポンスヘッダの<code>Content-Type</code>ヘッダを比較し、もし食い違っていたら前述の<code>.mime</code>タイプを作成し拡張子よりも<code>Content-Type</code>の値をリスペクトするという処理になってます。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/deno_dir.rs#L152-L175\">deno/src/deno_dir.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 152 to 175 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 151\" class=\"language-rust line-numbers\"><code class=\"language-rust\">    <span class=\"token macro property\">eprint!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Downloading {}...\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>module_name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// no newline</span>\n    <span class=\"token keyword\">let</span> maybe_source <span class=\"token operator\">=</span> <span class=\"token namespace\">http_util<span class=\"token punctuation\">::</span></span><span class=\"token function\">fetch_sync_string</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>module_name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token keyword\">let</span> <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>source<span class=\"token punctuation\">,</span> content_type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> maybe_source <span class=\"token punctuation\">{</span>\n      <span class=\"token macro property\">eprintln!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// next line</span>\n      <span class=\"token keyword\">match</span> p<span class=\"token punctuation\">.</span><span class=\"token function\">parent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">ref</span> parent<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token namespace\">fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">create_dir_all</span><span class=\"token punctuation\">(</span>parent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token class-name\">None</span> <span class=\"token operator\">=></span> <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n      <span class=\"token namespace\">deno_fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">write_file</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>p<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>source<span class=\"token punctuation\">,</span> <span class=\"token number\">0o666</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// Remove possibly existing stale .mime file</span>\n      <span class=\"token comment\">// may not exist. DON'T unwrap</span>\n      <span class=\"token keyword\">let</span> _ <span class=\"token operator\">=</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">remove_file</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>media_type_filename<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// Create .mime file only when content type different from extension</span>\n      <span class=\"token keyword\">let</span> resolved_content_type <span class=\"token operator\">=</span> <span class=\"token function\">map_content_type</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>p<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Some</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>content_type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">let</span> ext <span class=\"token operator\">=</span> p\n        <span class=\"token punctuation\">.</span><span class=\"token function\">extension</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token closure-params\"><span class=\"token closure-punctuation punctuation\">|</span>x<span class=\"token closure-punctuation punctuation\">|</span></span> x<span class=\"token punctuation\">.</span><span class=\"token function\">to_str</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap_or</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span><span class=\"token function\">unwrap_or</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">let</span> media_type <span class=\"token operator\">=</span> <span class=\"token function\">extmap</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>ext<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">if</span> media_type <span class=\"token operator\">==</span> <span class=\"token namespace\">msg<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">MediaType</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">Unknown</span>\n        <span class=\"token operator\">||</span> media_type <span class=\"token operator\">!=</span> resolved_content_type\n      <span class=\"token punctuation\">{</span>\n        <span class=\"token namespace\">deno_fs<span class=\"token punctuation\">::</span></span><span class=\"token function\">write_file</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>mt<span class=\"token punctuation\">,</span> content_type<span class=\"token punctuation\">.</span><span class=\"token function\">as_bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0o666</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span>\n      <span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>コードを取得するための HTTP クライアントは<a href=\"https://github.com/hyperium/hyper\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">hyper</a>というものを利用していました。低レベルだけど高速に動作する HTTP クライアントのようです。例えばリダイレクトのフォローを自前で書かないといけないくらいシンプルなクライアントです。コードにも TODO が書かれているんですが、現在のコードでは最大リダイレクト数が設定されておらず、リダイレクトループが発生するとハングするコードになってます。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/src/http_util.rs#L61-L62\">deno/src/http_util.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 61 to 62 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 60\" class=\"language-rust line-numbers\"><code class=\"language-rust\">  <span class=\"token comment\">// TODO(kevinkassimo): consider set a max redirection counter</span>\n  <span class=\"token comment\">// to avoid bouncing between 2 or more urls</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span></span></pre></div></p>\n<p>TypeScript のコードの取得は完了しました。次に V8 で実行できるように JavaScript にコンパイルする必要があります。\n<code>code_fetch_and_maybe_compile</code>の<code>DenoDir::code_fetch</code>を読みきったので続きを読んでいきます。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/77114fbda49382e397095d8214bd76996b0cfb57/src/isolate.rs#L375-L390\">deno/src/isolate.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 375 to 390 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/77114fbda49382e397095d8214bd76996b0cfb57\">77114fb</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 374\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">code_fetch_and_maybe_compile</span><span class=\"token punctuation\">(</span>\n  state<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">Arc</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">IsolateState</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span>\n  specifier<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n  referrer<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">CodeFetchOutput</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">DenoError</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> out <span class=\"token operator\">=</span> state<span class=\"token punctuation\">.</span>dir<span class=\"token punctuation\">.</span><span class=\"token function\">code_fetch</span><span class=\"token punctuation\">(</span>specifier<span class=\"token punctuation\">,</span> referrer<span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>out<span class=\"token punctuation\">.</span>media_type <span class=\"token operator\">==</span> <span class=\"token namespace\">msg<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">MediaType</span><span class=\"token punctuation\">::</span><span class=\"token class-name\">TypeScript</span>\n    <span class=\"token operator\">&amp;&amp;</span> out<span class=\"token punctuation\">.</span>maybe_output_code<span class=\"token punctuation\">.</span><span class=\"token function\">is_none</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token operator\">||</span> state<span class=\"token punctuation\">.</span>flags<span class=\"token punctuation\">.</span>recompile\n  <span class=\"token punctuation\">{</span>\n    <span class=\"token macro property\">debug!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\">>>>> compile_sync START\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    out <span class=\"token operator\">=</span> <span class=\"token function\">compile_sync</span><span class=\"token punctuation\">(</span>state<span class=\"token punctuation\">,</span> specifier<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>referrer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token macro property\">debug!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\">>>>> compile_sync END\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span>out<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>わかりやすくログが出てますが、<code>compile_sync</code>が ts を js にコンパイルする関数ですね。<code>compile_sync</code>の中身も追います。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/77114fbda49382e397095d8214bd76996b0cfb57/src/compiler.rs#L101-L118\">deno/src/compiler.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 101 to 118 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/77114fbda49382e397095d8214bd76996b0cfb57\">77114fb</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 100\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">compile_sync</span><span class=\"token punctuation\">(</span>\n  parent_state<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">Arc</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">IsolateState</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span>\n  specifier<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n  referrer<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token keyword\">str</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Option</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">CodeFetchOutput</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> req_msg <span class=\"token operator\">=</span> <span class=\"token function\">req</span><span class=\"token punctuation\">(</span>specifier<span class=\"token punctuation\">,</span> referrer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">let</span> compiler <span class=\"token operator\">=</span> <span class=\"token function\">lazy_start</span><span class=\"token punctuation\">(</span>parent_state<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">let</span> send_future <span class=\"token operator\">=</span> <span class=\"token namespace\">resources<span class=\"token punctuation\">::</span></span><span class=\"token function\">worker_post_message</span><span class=\"token punctuation\">(</span>compiler<span class=\"token punctuation\">.</span>rid<span class=\"token punctuation\">,</span> req_msg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  send_future<span class=\"token punctuation\">.</span><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">let</span> recv_future <span class=\"token operator\">=</span> <span class=\"token namespace\">resources<span class=\"token punctuation\">::</span></span><span class=\"token function\">worker_recv_message</span><span class=\"token punctuation\">(</span>compiler<span class=\"token punctuation\">.</span>rid<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> res_msg <span class=\"token operator\">=</span> recv_future<span class=\"token punctuation\">.</span><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">let</span> res_json <span class=\"token operator\">=</span> <span class=\"token namespace\">std<span class=\"token punctuation\">::</span></span><span class=\"token keyword\">str</span><span class=\"token punctuation\">::</span><span class=\"token function\">from_utf8</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>res_msg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token class-name\">CodeFetchOutput</span><span class=\"token punctuation\">::</span><span class=\"token function\">from_json</span><span class=\"token punctuation\">(</span>res_json<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>内部で呼び出されている<code>lazy_start</code>と、更にその中でコールされている<code>worker::spawn</code>も追います。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/77114fbda49382e397095d8214bd76996b0cfb57/src/compiler.rs#L82-L90\">deno/src/compiler.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 82 to 90 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/77114fbda49382e397095d8214bd76996b0cfb57\">77114fb</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 81\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">lazy_start</span><span class=\"token punctuation\">(</span>parent_state<span class=\"token punctuation\">:</span> <span class=\"token operator\">&amp;</span><span class=\"token class-name\">Arc</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">IsolateState</span><span class=\"token operator\">></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Resource</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> <span class=\"token keyword\">mut</span> cell <span class=\"token operator\">=</span> <span class=\"token constant\">C_RID</span><span class=\"token punctuation\">.</span><span class=\"token function\">lock</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> rid <span class=\"token operator\">=</span> cell<span class=\"token punctuation\">.</span><span class=\"token function\">get_or_insert_with</span><span class=\"token punctuation\">(</span><span class=\"token closure-params\"><span class=\"token closure-punctuation punctuation\">|</span><span class=\"token closure-punctuation punctuation\">|</span></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> resource <span class=\"token operator\">=</span>\n      <span class=\"token namespace\">workers<span class=\"token punctuation\">::</span></span><span class=\"token function\">spawn</span><span class=\"token punctuation\">(</span>parent_state<span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"compilerMain()\"</span><span class=\"token punctuation\">.</span><span class=\"token function\">to_string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    resource<span class=\"token punctuation\">.</span>rid\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token class-name\">Resource</span> <span class=\"token punctuation\">{</span> rid<span class=\"token punctuation\">:</span> <span class=\"token operator\">*</span>rid <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/77114fbda49382e397095d8214bd76996b0cfb57/src/workers.rs#L53-L87\">deno/src/workers.rs</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 53 to 87 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/77114fbda49382e397095d8214bd76996b0cfb57\">77114fb</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"rust\"><pre style=\"counter-reset: linenumber 52\" class=\"language-rust line-numbers\"><code class=\"language-rust\"><span class=\"token keyword\">pub</span> <span class=\"token keyword\">fn</span> <span class=\"token function-definition function\">spawn</span><span class=\"token punctuation\">(</span>\n  state<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Arc</span><span class=\"token operator\">&lt;</span><span class=\"token class-name\">IsolateState</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span>\n  js_source<span class=\"token punctuation\">:</span> <span class=\"token class-name\">String</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">-></span> <span class=\"token namespace\">resources<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Resource</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// TODO This function should return a Future, so that the caller can retrieve</span>\n  <span class=\"token comment\">// the JSError if one is thrown. Currently it just prints to stderr and calls</span>\n  <span class=\"token comment\">// exit(1).</span>\n  <span class=\"token comment\">// let (js_error_tx, js_error_rx) = oneshot::channel::&lt;JSError>();</span>\n  <span class=\"token keyword\">let</span> <span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">,</span> c<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token namespace\">oneshot<span class=\"token punctuation\">::</span></span><span class=\"token function\">channel</span><span class=\"token punctuation\">::</span><span class=\"token operator\">&lt;</span><span class=\"token namespace\">resources<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Resource</span><span class=\"token operator\">></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> builder <span class=\"token operator\">=</span> <span class=\"token namespace\">thread<span class=\"token punctuation\">::</span></span><span class=\"token class-name\">Builder</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">name</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"worker\"</span><span class=\"token punctuation\">.</span><span class=\"token function\">to_string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> _tid <span class=\"token operator\">=</span> builder\n    <span class=\"token punctuation\">.</span><span class=\"token function\">spawn</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">move</span> <span class=\"token closure-params\"><span class=\"token closure-punctuation punctuation\">|</span><span class=\"token closure-punctuation punctuation\">|</span></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">let</span> <span class=\"token punctuation\">(</span>worker<span class=\"token punctuation\">,</span> external_channels<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token class-name\">Worker</span><span class=\"token punctuation\">::</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>state<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token keyword\">let</span> resource <span class=\"token operator\">=</span> <span class=\"token namespace\">resources<span class=\"token punctuation\">::</span></span><span class=\"token function\">add_worker</span><span class=\"token punctuation\">(</span>external_channels<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      p<span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span>resource<span class=\"token punctuation\">.</span><span class=\"token function\">clone</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token namespace\">tokio_util<span class=\"token punctuation\">::</span></span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token closure-params\"><span class=\"token closure-punctuation punctuation\">|</span><span class=\"token closure-punctuation punctuation\">|</span></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token punctuation\">(</span><span class=\"token closure-params\"><span class=\"token closure-punctuation punctuation\">|</span><span class=\"token closure-punctuation punctuation\">|</span></span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">JSError</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n          worker<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"denoMain()\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n          worker<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"workerMain()\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n          worker<span class=\"token punctuation\">.</span><span class=\"token function\">execute</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>js_source<span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n          worker<span class=\"token punctuation\">.</span><span class=\"token function\">event_loop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span><span class=\"token punctuation\">;</span>\n          <span class=\"token class-name\">Ok</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">or_else</span><span class=\"token punctuation\">(</span><span class=\"token closure-params\"><span class=\"token closure-punctuation punctuation\">|</span>err<span class=\"token punctuation\">:</span> <span class=\"token class-name\">JSError</span><span class=\"token closure-punctuation punctuation\">|</span></span> <span class=\"token punctuation\">-></span> <span class=\"token class-name\">Result</span><span class=\"token operator\">&lt;</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">JSError</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n          <span class=\"token macro property\">eprintln!</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"{}\"</span><span class=\"token punctuation\">,</span> err<span class=\"token punctuation\">.</span><span class=\"token function\">to_string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          <span class=\"token namespace\">std<span class=\"token punctuation\">::</span>process<span class=\"token punctuation\">::</span></span><span class=\"token function\">exit</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      resource<span class=\"token punctuation\">.</span><span class=\"token function\">close</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  c<span class=\"token punctuation\">.</span><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">unwrap</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>worker::spawn の中<code>worker.execute</code>にて<code>denoMain()</code>, <code>workerMain()</code>, <code>引数で渡されたコード</code>を実行するようになっています。引数で渡されたコードは何かというと<code>lazy_start</code>を見ての通り<code>compilerMain()</code>です。<br>\nWorker は main 関数で生成された V8 Isolate とは隔離された別の Isolate を生成しています。この Isolate もまたスナップショットから復元されているので高速です。\nこれら３つの関数が実行されたあとに、req 関数で生成した<code>specifier</code>と<code>referrer</code>を worker に送信し、TypeScript のコンパイルを実行します。</p>\n<p>次に<code>compilerMain</code>の定義を追ってみます。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/ee9c627cc5f92898d104e9359059b57354c9f83c/js/compiler.ts#L526-L544\">deno/js/compiler.ts</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 526 to 544 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/ee9c627cc5f92898d104e9359059b57354c9f83c\">ee9c627</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre style=\"counter-reset: linenumber 525\" class=\"language-typescript line-numbers\"><code class=\"language-typescript\"><span class=\"token comment\">// provide the \"main\" function that will be called by the privilaged side when</span>\n<span class=\"token comment\">// lazy instantiating the compiler web worker</span>\nwindow<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">compilerMain</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token function\">compilerMain</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// workerMain should have already been called since a compiler is a worker.</span>\n  <span class=\"token keyword\">const</span> encoder <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">TextEncoder</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> decoder <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">TextDecoder</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  compiler<span class=\"token punctuation\">.</span>recompile <span class=\"token operator\">=</span> startResMsg<span class=\"token punctuation\">.</span><span class=\"token function\">recompileFlag</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">recompile </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>compiler<span class=\"token punctuation\">.</span>recompile<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  window<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">onmessage</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> data <span class=\"token punctuation\">}</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> data<span class=\"token operator\">:</span> Uint8Array <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> json <span class=\"token operator\">=</span> decoder<span class=\"token punctuation\">.</span><span class=\"token function\">decode</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> lookup <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> CompilerLookup<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">const</span> moduleMetaData <span class=\"token operator\">=</span> compiler<span class=\"token punctuation\">.</span><span class=\"token function\">compile</span><span class=\"token punctuation\">(</span>lookup<span class=\"token punctuation\">.</span>specifier<span class=\"token punctuation\">,</span> lookup<span class=\"token punctuation\">.</span>referrer<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">const</span> responseJson <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>moduleMetaData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> encoder<span class=\"token punctuation\">.</span><span class=\"token function\">encode</span><span class=\"token punctuation\">(</span>responseJson<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">postMessage</span><span class=\"token punctuation\">(</span>response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>Compiler の compile メソッドは<a href=\"https://github.com/denoland/deno/blob/ee9c627cc5f92898d104e9359059b57354c9f83c/js/compiler.ts#L235-L318\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">js/compiler.ts</a>に定義されています。コードがやや長いので引用はしません。<br>\n大まかな処理内容としては、<code>typescript</code>モジュールを使ってコンパイルしたり型検査したりしてます。JSON に関しては<a href=\"https://github.com/denoland/deno/blob/ee9c627cc5f92898d104e9359059b57354c9f83c/js/compiler.ts#L122\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code>jsonEsmTemplate</code></a>という薄いラッパーを噛ませて独自コンパイルしています。それ以外（TypeScript, JavaScript）に関しては、LanguageService の<code>getEmitOutput</code>を用いてソースマップとコンパイル後の JavaScript を入手し、その後に型検査 etc を実行しもしエラーがあれば異常終了、エラーがなければ JavaScript にソースマップをくっつけてキャッシュに書き込んで完了という処理になっています。<br>\n検査する項目は独自に絞って処理の高速化を図っています。このやり方のほうが 3 倍ほど通常の検査より高速だそうです。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/ee9c627cc5f92898d104e9359059b57354c9f83c/js/compiler.ts#L262-L274\">deno/js/compiler.ts</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 262 to 274 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/ee9c627cc5f92898d104e9359059b57354c9f83c\">ee9c627</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre style=\"counter-reset: linenumber 261\" class=\"language-typescript line-numbers\"><code class=\"language-typescript\">      <span class=\"token comment\">// Get the relevant diagnostics - this is 3x faster than</span>\n      <span class=\"token comment\">// `getPreEmitDiagnostics`.</span>\n      <span class=\"token keyword\">const</span> diagnostics <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n        <span class=\"token comment\">// TypeScript is overly opinionated that only CommonJS modules kinds can</span>\n        <span class=\"token comment\">// support JSON imports.  Allegedly this was fixed in</span>\n        <span class=\"token comment\">// Microsoft/TypeScript#26825 but that doesn't seem to be working here,</span>\n        <span class=\"token comment\">// so we will ignore complaints about this compiler setting.</span>\n        <span class=\"token operator\">...</span>service\n          <span class=\"token punctuation\">.</span><span class=\"token function\">getCompilerOptionsDiagnostics</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>diagnostic <span class=\"token operator\">=></span> diagnostic<span class=\"token punctuation\">.</span>code <span class=\"token operator\">!==</span> <span class=\"token number\">5070</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token operator\">...</span>service<span class=\"token punctuation\">.</span><span class=\"token function\">getSyntacticDiagnostics</span><span class=\"token punctuation\">(</span>fileName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token operator\">...</span>service<span class=\"token punctuation\">.</span><span class=\"token function\">getSemanticDiagnostics</span><span class=\"token punctuation\">(</span>fileName<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>なお TypeScript の LanguageService の詳しい説明は<a href=\"https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">公式の wiki</a>にあったのでそちらを参照して下さい。</p>\n<p>JavaScript へのコンパイルが完了し、ようやく指定されたモジュールを実行できるようになりました。最後に<code>libdeno::deno_execute_mod</code>を読みます。<code>libdeno::deno_execute_mod</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/api.cc#L129\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/api.cc</a>に定義されています。実質的な処理は<code>deno::ExecuteMod</code>に書いてあります。<code>deno::ExecuteMod</code>は<a href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L592\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libdeno/binding.cc</a>に定義されています。V8 で JavaScript のコードを実行するくだりは<code>deno::Execute</code>のときに書いた説明を参照して下さい。</p>\n<p>\n<div class=\"gprgh-container\">\n  <div class=\"gprgh-filename-container\">\n    <a class=\"gprgh-filename\" href=\"https://github.com/denoland/deno/blob/c870cf40823a4900278f8ddf03489338c169878b/libdeno/binding.cc#L603-L624\">deno/libdeno/binding.cc</a>\n  </div>\n  <span class=\"gprgh-meta\">\n    Lines 603 to 624 in <a class=\"gprgh-meta-sha\" href=\"https://github.com/denoland/deno/commit/c870cf40823a4900278f8ddf03489338c169878b\">c870cf4</a>\n  </span>\n</div>\n\n<div class=\"gatsby-highlight\" data-language=\"cpp\"><pre style=\"counter-reset: linenumber 602\" class=\"language-cpp line-numbers\"><code class=\"language-cpp\">  <span class=\"token keyword\">auto</span> maybe_module <span class=\"token operator\">=</span> <span class=\"token function\">CompileModule</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> js_filename<span class=\"token punctuation\">,</span> source<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>maybe_module<span class=\"token punctuation\">.</span><span class=\"token function\">IsEmpty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">DCHECK</span><span class=\"token punctuation\">(</span>try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">HasCaught</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">HandleException</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">Exception</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">DCHECK</span><span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>try_catch<span class=\"token punctuation\">.</span><span class=\"token function\">HasCaught</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">auto</span> <span class=\"token keyword\">module</span> <span class=\"token operator\">=</span> maybe_module<span class=\"token punctuation\">.</span><span class=\"token function\">ToLocalChecked</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">auto</span> maybe_ok <span class=\"token operator\">=</span> <span class=\"token keyword\">module</span><span class=\"token operator\">-></span><span class=\"token function\">InstantiateModule</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> ResolveCallback<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>maybe_ok<span class=\"token punctuation\">.</span><span class=\"token function\">IsNothing</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">CHECK_EQ</span><span class=\"token punctuation\">(</span>v8<span class=\"token double-colon punctuation\">::</span>Module<span class=\"token double-colon punctuation\">::</span>kInstantiated<span class=\"token punctuation\">,</span> <span class=\"token keyword\">module</span><span class=\"token operator\">-></span><span class=\"token function\">GetStatus</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>resolve_only<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">auto</span> result <span class=\"token operator\">=</span> <span class=\"token keyword\">module</span><span class=\"token operator\">-></span><span class=\"token function\">Evaluate</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div></p>\n<p>ここまでの内容で、deno コマンドを実行し、TypeScript が実行されるまでの処理が追えたと思います。</p>\n<div class=\"gatsby-highlight\" data-language=\"shell\"><pre class=\"language-shell\"><code class=\"language-shell\">$ <span class=\"token function\">cat</span> tests/002_hello.ts\nconsole.log<span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n$ ./target/debug/deno tests/002_hello.ts\nHello World</code></pre></div>\n<h2 id=\"さいごに\" style=\"position:relative;\"><a href=\"#%E3%81%95%E3%81%84%E3%81%94%E3%81%AB\" aria-label=\"さいごに permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>さいごに</h2>\n<p>実行されるすべての行を網羅したわけではありませんが、ビルドプロセスも含めて一連の流れを追えたと思います。Rust、C++、TypeScript とレイヤをまたぐ処理がかなり多いので、わかってしまえばすんなり読めますが、初見はかなり大変でした。<br>\nC++は V8 以外の処理をなるべく書かず意図的に Rust 側に寄せているように感じました。Rust で書いたほうが自分の足を撃ちにくいプログラムになると思うので、これが功を奏すのかどうか、1~2 年後が楽しみです。</p>\n<p>記事内ではあまり触れてませんが、コードを読んでる過程で TODO や FIXME コメントが大量に見つかったので、Deno コアに対するコントリビュートのネタは、コード読むとたくさん見つかると思います。</p>\n<p>他にも Worker の実装、セキュリティモデルの実装、TypeScript 製の外部モジュールの依存解決、イベントループや TaskQueue 関連の Node.js との差異、ビルドプロセスの詳細など、まだまだ読みたい Deno のコードがあるので、読んで理解できたら記事書きます。</p>","timeToRead":47,"frontmatter":{"title":"Dive into Deno：プロセス起動からTypeScriptが実行されるまで","tags":["JavaScript","TypeScript","Rust","Deno"],"date":"January 19, 2019","featuredImage":null}}},"pageContext":{"slug":"/code-reading-of-deno-boot-process/","previous":{"fields":{"slug":"/benchmark-of-lazy-frame-loading/"},"frontmatter":{"title":"ChromeのBlink LazyLoadを有効にしたらページのロード時間が約10倍早くなった","tags":["JavaScript","Google Chrome"]}},"next":{"fields":{"slug":"/what-benefit-of-intl-number-format/"},"frontmatter":{"title":"Intl.NumberFormatでゼロ埋めや％表記などの数値表現を楽に実装する","tags":["JavaScript","Node.js"]}}}},
    "staticQueryHashes": ["2585454260","2954598359"]}