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

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

--deny-*オプション

--deny-*という新しいオプションが導入されました。このオプションにより、Denoに対して特定の操作のみを明示的に拒否させることができます。

例えば、以下の場合、Denoにwrite権限のみを拒否させています。

$ deno run --allow-all --deny-write main.js

このように--allow-*オプションと--deny-*オプションは併用することが可能で、その場合、--deny-*オプションの方が優先されます。

また、--deny-*には--allow-*と同様に、リスト形式で対象を指定することもできます。

$ deno run --allow-read --deny-read=README.md main.js

上記の場合、./README.mdへの読み込みのみが拒否され、それ以外のファイルの読み込みは許可されます。

{
  const content = await Deno.readTextFile("Makefile"); // => OK
  console.info(content);
}

{
  const content = await Deno.readTextFile("README.md"); // => PermissionDenied
  console.info(content);
}

deno_modulesディレクトリの導入

⚠️この機能はまだunstableという扱いのため、今後、機能などに変更が入る可能性があります。

また、現在、deno_modulesvendorにリネームするPRも作成されており、今後ディレクトリやオプションなどの名前が変わる可能性も高そうです。

deno.jsondenoModulesDirという新しいオプションが導入されました。

このオプションにtrueを設定すると、リモートモジュールがdeno_modulesというディレクトリにダウンロードされるように挙動が変更されます。

{
  "denoModulesDir": true
}

この状態でスクリプトを実行すると、依存しているリモートモジュールがdeno_modulesに保存されます。

import { blue } from "https://deno.land/std@0.197.0/fmt/colors.ts";
console.info(blue("foobar"));

deno_modulesにダウンロードされたモジュールは、deno vendorコマンドと同様の形式で保存されます。

そのため、テキストエディタを使用してデバッグや編集などを行うことができます。

$ vim deno_modules/deno.land/std@0.197.0/fmt/colors.ts

deno test

JUnit/dotレポーターのサポート

テストランナーでJUnitレポーターとdotレポーターが実装されました。

--reporterオプションによって、使用したいレポーターを指定することができます。

# dotレポーターを有効化します
$ deno test --allow-read --allow-env --reporter=dot

# JUnitレポーターを有効化します
$ deno test --allow-read --allow-env --reporter=junit

# prettyレポーターを有効化します (デフォルトのレポーター)
$ deno test --allow-read --allow-env --reporter=pretty

JUnitレポーターはデフォルトで標準出力にレポートを出力しますが、--junit-pathオプションを指定することで指定されたファイルへレポートを出力することもできます。

# report.xmlにJUnit形式のレポートを出力します
$ deno test --allow-read --allow-env --junit-path=report.xml

また、--reporter--junit-pathは併用することも可能です。

# dotレポーターを使って標準出力にレポートを出力しつつ、report.xmlにJUnit形式のレポートを書き出します
$ deno test --allow-read --allow-env --reporter=dot --junit-path=report.xml

deno bench - BenchContext型が実装

Deno.BenchContext型が実装されました。Deno.benchに渡した関数の第一引数として受け取ることが出来ます。

このオブジェクトはstart/endメソッドを持っていて、ベンチマークの実行開始/終了タイミングをユーザが柔軟に制御できます。

Deno.bench("someHeavyComputation", async (t) => {
  await setup(); // ここの実行については計測対象から除外されます

  t.start(); // 計測開始
  await someHeavyComputation();
  t.end(); // 計測終了

  await cleanup(); // ここの実行についても計測対象から除外されます
});

また、deno benchコマンドが出力する指標としてiter/s(1秒あたりの繰り返し数)が追加されています。

$ deno bench bench.ts
...

file:///home/uki00a/ghq/github.com/uki00a/work/bench.ts
benchmark      time (avg)        iter/s             (min … max)       p75       p99      p995
--------------------------------------------------------------- -----------------------------
sum            15.58 ns/iter  64,195,016.8   (11.62 ns … 43.13 ns)  18.57 ns  30.28 ns  33.71 ns

deno compile - --no-terminalオプションのサポート

ターゲットがWindowsの場合にこのオプションを指定しておくと、生成された実行可能ファイルを実行する際にターミナルウィンドウが開かなくなります。

Node.js互換性の改善

node:testが実装

Deno本体でnode:testモジュールが実装されました。

import assert from "node:assert";
import { test } from "node:test";

function sum(...numbers: Array<number>): number {
  return numbers.reduce((a, b) => a + b, 0);
}

test("sum", () => {
  assert.strictEqual(sum(), 0);
  assert.strictEqual(sum(987), 987);
  assert.strictEqual(sum(1, 2, 3), 6);
});

node:testで書かれたテストは通常通りdeno testコマンドで実行することができます。

いまのところ、beforeEachなどのフックやdescribe/it, mockなどのAPIについては未実装のようです。

node:os - getPriority/setPriority/userInfoが実装

これらのAPIの実行には--allow-sys権限が必要です。

import { getPriority, userInfo } from "node:os";

console.info(userInfo());
console.info(getPriority());

その他

  • deno runpackage.jsonbinエントリに記載されていないファイルの実行がサポートされました。

  • npmパッケージに含まれるJSONファイルをimportできるようになりました。

    import tsconfig from "npm:@tsconfig/recommended@1.0.2/tsconfig.json" assert { type: "json" };
    
    console.info(tsconfig);
    

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

trueを指定すると、fetchHostヘッダーをカスタマイズできるようになります。

const client = Deno.createHttpClient({
  allowHost: true,
});

const res = await fetch("http://localhost:8000", {
  headers: { host: "example.com" },
  client,
});

WebSocket

WebSocketコンストラクタでhttp:/https:URLの指定がサポートされました。

const ws = new WebSocket("http://localhost:8080");

バグ修正など

CLI

  • Denoがリモートモジュールのダウンロードに失敗した際に、一度だけリトライが行われるように挙動が改善されました。
  • deno.jsoncompilerOptions.jsxcompilerOptions.jsxImportSourceに不正な値が設定された際にエラーが発生するように修正されました。

deno lsp

  • Import Mapsでマッピングが定義されたnode:<package>がうまくハンドルされない問題が修正されました。
  • suggest.autoImports: falseが指定された際に、importされていないモジュールからのシンボルが補完されないように挙動が修正されています。

Deno.serve

cloneされたRequesturlプロパティを参照すると、エラーが発生する問題が修正されています。

const ac = new AbortController();
const server = Deno.serve({
  signal: ac.signal,
  handler: (req) => {
    req.clone().url; // => OK
    return new Response("OK");
  },
});

Web API

  • MessageEvent.isTrustedが常にfalseに設定される問題が修正されました。
  • Worker内でdynamic importを使うと、プロセスがハングする問題が修正されました。

参考