経験は何よりも饒舌

10年後に真価を発揮するかもしれないブログ 

nodejs/node と denoland/deno_std/node のアーキテクチャ

English version: Architecture of nodejs/node and denoland/deno_std/node - 経験は何よりも饒舌


この記事は Advent Calendar 2021 Deno の16日目です。
趣味でdenoland/deno_stdにコントリビュートしており、特に denoland/deno_std/node をよく見ているので、nodejs/nodedenoland/deno_std/node の現時点(2021/12/16)でのNode APIにまつわるアーキテクチャの違いをざっくり書いていこうと思います。

APIの実装場所

nodejs/node

node/libに実装されています。
Query stringを例にすると、node/lib/querystring.jsでロジックが実装されていて、ここでexportされています。
また、exportする必要のない内部のコードがnode/lib/internalで実装されています。
Query stringではencordStrなどの関数がexportされてnode/lib/querystring.jsでimportされています。

denoland/deno_std

deno_std/nodeに実装されています。
deno_std/node/querystirng.tsnodejs/node/lib/querystring.jsでexportされているロジックと互換性のあるAPIここでexportされています。
また、deno_std/node/internalで、nodejs/node/lib/internal相当の実装がされています。

Implementation Language

nodejs/node

JavaScriptC++で実装されています。
URLを例にすると、node/lib/url.jsnode/lib/internal/url.jsといったJavaScriptの実装の中で一部、internalBindingによってC++のコードが呼び出されています。
例えばdomainToASCIIの実装はnode/src/node_url.ccにされています。
ちなみに、なぜJavaScriptで実装されていないのかと疑問を持ち、helpレポジトリでWhy domainToASCII is written by C++ not JS?と伺ったところ、for perf reasonsという回答をいただきました。
また、各所でprimordialsが使われています。
primordialsについてはプロトタイプ汚染周りの提案と primordials.jsが詳しいです。

denoland/deno_std

JavaScriptとTypeScriptで実装されています。
例えばQuery stringはquerystring.tsで実装されていますが、Buffernode/_buffer.jsで実装されており、node/buffer.ts@deno-typesnode/_buffer.d.tsが指定されています。
NodeのinternalBindingに相当する実装はnode/internal_bindingでTypeScriptにより実装されています。
primordialsは、denoland/denoには導入されていますが、denoland/deno_stdには導入されていません。

テスト

nodejs/node

node/testにあります。
例えばURLのテストはnode/test/parallel/test-url-*.jsで実装されています。
実行方法などはpull-requests.mdにまとまっています。

denoland/deno_std

node/_tools/config.jsonで、nodejs/node/testにあるテストのファイル名を指定し、node/_tools/setup.tsで取得し、node/_tools/suitesに配置しています。
実行方法などはnode/README.mdにまとまっています。