Deno v1.29がリリースされました。

この記事では主な変更点などについて解説します。

サブプロセスAPIに関する変更

Deno.spawn, Deno.spawnSync, Deno.spawnChildの削除

Deno v1.28Deno.Commandが実装されたため、下記のAPIが削除されています。

  • Deno.spawn
  • Deno.spawnSync
  • Deno.spawnChild

このあたりの背景などについては、下記の記事で詳しく解説されています。

また、Deno.Commandについてもv1.28.3でAPIが若干変更されています。

Deno.spawn系統のAPIからDeno.Commandへの移行について

Deno.spawn()Deno.Child#output(), Deno.spawnSync()Deno.Child#outputSync()で代用できます。

const command = new Deno.Command("deno", {
  args: ["info", "--json"],
});
const status = await command.output();
if (status.success) {
  console.info(new TextDecoder().decode(status.stdout));
}

Deno.spawnChild()Deno.Child#spawn()で代用できます。

const command = new Deno.Command("deno", {
  args: ["fmt", "--ext=json", "-"],
  stdin: "piped",
  stdout: "piped"
});
const child = command.spawn();
const file = await Deno.open("deno.json");
file.readable.pipeTo(child.stdin);

const status = await child.status;
if (status.success) {
  const output = [];
  for await (const x of child.stdout.pipeThrough(new TextDecoderStream())) {
    output.push(x);
  }
  console.info(output.join(''));
}

Deno.Command#spawnstdoutstderrオプションのデフォルト値が"inherit"に変更

Deno.Commandの作成時にstdoutstderrオプションが未設定の場合、これらのオプションのデフォルト値が"inherit"に変更されています。

Deno.Command#outputDeno.Command#outputSyncについては引き続き"piped"がデフォルト値として扱われます。

Node.js互換性の改善

NPM_CONFIG_REGISTRY環境変数

Denoはデフォルトでhttps://registry.npmjs.orgからnpmパッケージをダウンロードします。

今回のリリースからNPM_CONFIG_REGISTRY環境変数がサポートされ、npmパッケージをダウンロードする際のレジストリをカスタマイズできるようになりました。

$ NPM_CONFIG_REGISTRY=https://registry.npmjs.org/ deno run --allow-env --allow-read --allow-write npm:make-dir-cli@3.0.0 ./path/to/dir

将来のリリースでは、パッケージスコープごとのレジストリや認証情報の設定などをサポートすることなども検討されているようです。

deno installでのnpm:のサポート

deno installコマンドでnpmパッケージから提供されるコマンドのインストールがサポートされました。(Deno v1.28.1)

例えば、下記はmake-dir-cliパッケージをインストールする例です。

$ deno install --allow-env --allow-read --allow-write npm:make-dir-cli@3.0.0

$ which make-dir-cli
/home/uki00a/.deno/bin/make-dir-cli

deno.json(c)に関する改善

benchフィールドのサポート

deno.json(c)deno benchのカスタマイズがサポートされました。

現在ではbench.files.includeフィールドとbench.files.excludeによるファイルの絞り込みがサポートされています。

{
  "bench": {
    "files": {
      "include": ["./benchmark"]
    }
  }
}

ロックファイルに関する挙動の制御

deno.json(c)でロックファイルに関する挙動を制御できるようになりました。

例えば、lock: falseを指定することでロックファイルの適用を無効化できます(--no-lock相当の挙動)

{
  "lock": false
}

また、lockオプションにパスを指定することで、ロックファイルの名前をカスタマイズすることも可能です。

{
  "lock": "./lock.json"
}

deno initコマンドの改善

deno initコマンドで新しくdeno.jsonc及びmain_bench.tsの生成がサポートされました。

$ deno init ./my-deno-project


$ ls ./my-deno-project
deno.jsonc  main.ts  main_bench.ts  main_test.ts

REPLの改善

deno replコマンドのパーミッションが変更

deno replコマンドを実行した際は、デフォルトで一切の権限がない状態でREPLが起動するように挙動が変更されています。

Deno v1.28までは、deno replコマンドは全ての権限が許可された状態でREPLを起動していましたが、これはDenoの"secure by default"の考えに反するということが変更の背景のようです。

ただし、denoコマンドを単独で実行した場合は、引き続き全ての権限が与えられた状態でREPLが起動されます。

この変更に伴い、deno replコマンドで--allow-read--allow-netなどのオプションがサポートされています。

$ deno repl --allow-read

npm:のサポート

REPLでnpmパッケージの読み込みがサポートされています。

$ deno repl --allow-env --allow-read
Deno 1.29.1
exit using ctrl+d, ctrl+c, or close()
> import chalk from "npm:chalk@5.0.0";
undefined
> chalk.green("foobar");
"\x1b[32mfoobar\x1b[39m"

deno lintコマンドなどでnode_modules.gitが無視されるように

元々、deno fmtコマンドではnode_modules.gitが無視されていましたが、deno lintなどのコマンドではこれらのディレクトリは無視されませんでした。

今回のリリースでは、deno lintなどのコマンドでもデフォルトでnode_modules.gitが無視されるようになり、一貫性が向上しています。

新しいCLIオプション

deno checkコマンドで--allオプションがサポート

deno runコマンドでリモートモジュールも含む全コードの型チェックを行いたい場合、下記のように--check=allオプションを指定する必要があります。

$ deno run --check=all mod.ts

それに対して、deno checkコマンドでリモートモジュールも含む全コードの型チェックを行う場合は、下記のように--remoteオプションを指定する必要がありました。

$ deno check --remote mod.ts

同様の挙動を実現するために、deno runでは--check=allを指定するのに対して、deno checkでは--remoteを指定する必要があり、オプションに一貫性がないという課題がありました。

この問題を解消するために、deno checkコマンドで--allオプションがサポートされました。

# Deno v1.28における`deno check --remote`と同様の振る舞いをします
$ deno check --all mod.ts

--inspect-waitオプション

元々、Denoには--inspect--inspect-brkというデバッガに関する2種類のオプションがありました。

これらのオプションはそれぞれ下記のように動作します。

--inspect:

  1. デバッガを有効化する
  2. コードを実行する

--inspect-brk:

  1. デバッガを有効化する
  2. デバッガとの間でセッションが確率されるまで待機する
  3. コードの最初の行で実行をストップする

今回のリリースでは、新しく--inspect-waitオプションが追加されています。

挙動としては、--inspect--inspect-brkの中間のような振る舞いをします。

  1. デバッガを有効化する
  2. デバッガとの間でセッションが確率されるまで待機する
  3. コードを実行する

Deno.TcpConnsetNoDelaysetKeepAliveメソッドが安定化

Deno v1.19で実装されたsetNoDelayメソッドとsetKeepAliveメソッドが安定化されました。

今後は--unstableオプションなしでこれらのAPIを利用できます。

Deno.writeFilecreateNewオプションがサポート

Deno.writeFilecreateNewオプションが追加されています。

await Deno.writeFile(path, content, { createNew: true });

このオプションにtrueが指定された場合、対象ファイルが新しく作成されます。

もし対象のファイルがすでに存在する場合はエラーが発生します。

このオプションのデフォルト値はfalseです

Deno.dlopenの型推論が改善

例えば、下記のようにDeno.dlopenを呼んだとします。

const lib = Deno.dlopen({
  doSomething: {
    parameters: ["i32", "bool"],
    result: "i8",
  },
});

Deno v1.28ではlib.doSomethingの引数の型はArray<number | boolean>として推論されます。

今回のリリースではlib.doSomethingの引数が[number, boolean]型として推論されるように改善され、使い勝手が向上しています。

TypeScript v4.9

Denoの内部に搭載されているTypeScriptのバージョンがv4.9.3へアップデートされました。

これにより、Denoでもsatisfiesオペレータなどを活用できるようになりそうです。

その他のバグ修正

  • 別のRequestオブジェクトから新しいRequestを作る際に、optionsが直接変更されてしまう問題が修正されています。

    const req = new Request("https://example.com/", { method: "POST", body: "foobar" });
    new Request(req, { body: "foo" });
    await req.text(); // v1.28: "foo", v1.29: "foobar"
    
  • deno compileコマンドでdeno.json(c)で指定されたImport Mapsファイルが無視されてしまう問題が修正されています。

  • プログラム中でnpm:が使用されていて かつ --inspect-brkなどでデバッガが有効化されている場合、ランタイムエラーが報告されなくなる問題が修正

  • --allow-ffiの挙動の改善

    • 例えば、--allow-ffi=somelibのようにパスを指定した際に、下記のような読み込みが許可されるようになりました。
    Deno.dlopen("somelib/lib.so", symbols);
    
  • deno vendorコマンドで名前がhttpで始まるbare import文が適切に処理されない問題が修正されています。

参考