Deno v1.24がリリースされました。
この記事では主な変更点などについて解説します。
--check
オプション指定時のトランスパイルの挙動が変更
tscがトランスパイル用途では使用されなくなりました。
型チェック | トランスパイル | |
---|---|---|
--check (v1.23) | tsc | tsc |
--no-check (v1.23) | - | swc |
--check (v1.24) | tsc | swc |
--no-check (v1.24) | - | swc |
これにより、トランスパイルの効率化が見込まれます。
また、tscの実行結果をSQLiteにキャッシュする仕組みも導入されており、型チェックについても効率化が図られています。($DENO_DIR/check_cache_v1
にSQLiteのデータベースファイルが作成されます)
FFI(Deno.dlopen
)の改善
v1.23.3でV8 Fast API Calls+JITコンパイルの導入による最適化が実施されました。
今回のリリースでは、64ビット値を取り扱う関数に対してもV8 Fast API Callsを利用した最適化が適用されるように改善されています。
サブプロセスAPIへの変更
Deno v1.21 で入ったサブプロセスAPIに変更が加わっています。
Deno.Child.unref()
とDeno.Child.ref()
のサポート
挙動としてはDeno.refTimerやDeno.unrefTimerと同様で、Deno.Child.unref()
を呼ぶと、対象の子プロセスがDenoの終了をブロックしなくなります。
const child = await Deno.spawnChild("some_long_running_process", { args });
child.unref();
(破壊的変更) Deno.Child
の型定義が変更
Deno.spawnChild
で返却されるDeno.Child
のstdio関連のプロパティに関する型定義が変更されています。
class Child<T extends SpawnOptions> {
readonly stderr: T["stderr"] extends "inherit" | "null" ? null : ReadableStream<Uint8Array>;
readonly stdin: T["stdin"] extends "piped" ? WritableStream<Uint8Array> : null;
readonly stdout: T["stdout"] extends "inherit" | "null" ? null :
// ...
}
class Child {
get stdin(): WritableStream<Uint8Array>;
get stdout(): ReadableStream<Uint8Array>;
get stderr(): ReadableStream<Uint8Array>;
// ...
}
stdin
/stdout
/stderr
がgetterに変更されており、"piped"
が指定されていないストリームを参照した際に、TypeScriptの型エラーではなく実行時エラー(TypeError
)が発生するように修正されています。
const child = Deno.spawnChild("echo", { args: ["foobar"], stdout: "null" });
const stream = child.stdout.pipeThrough(new TextDecoderStream()); // => v1.23.4までは型エラー、v1.24.0からは実行時エラー
(破壊的変更) Deno.SpawnOutput
の型定義が変更
Deno.spawn()
またはDeno.spawnSync()
で返却されるDeno.SpawnOutput
の型定義が変更されています。
interface SpawnOutput<T extends SpawnOptions> {
status: ChildStatus;
stderr: T["stderr"] extends "inherit" | "null" ? null : Uint8Array;
stdout: T["stdout"] extends "inherit" | "null" ? null : Uint8Array;
}
interface SpawnOutput extends ChildStatus {
get stderr(): Uint8Array;
get stdout(): Uint8Array;
}
interface ChildStatus {
code: number;
signal: Signal | null;
success: boolean;
}
こちらもDeno.Child
と同様にジェネリクスを使用しないように型定義が変更されています。
また、Deno.SpawnOutput
がDeno.ChildStatus
をextend
することで、よりフラットな構造へ変更されています。
const output = await Deno.spawn("echo", { args: ["foobar"] });
output.success; // => true
output.signal; // => null
import.meta.resolve()
がサポート
import.meta.resolve()
が実装されました。
これを使うことで、
const worker = new URL("./worker.js", import.meta.url).href;
と同様の処理が下記のようにして実現できます。
const workerURL = import.meta.resolve("./worker.js");
また、import.meta.resolve()
はImport mapsも解釈してくれます。
{
"imports": {
"redis": "https://deno.land/x/redis@v0.26.0/mod.ts"
}
}
このようなImport mapsファイルがあった場合、import.meta.resolve()
は下記のような結果を返してくれます。
import.meta.resolve("redis"); // => https://deno.land/x/redis@v0.26.0/mod.ts
"unhandledrejection"
イベントのサポート
ブラウザと同様に、reject
されたcatch
されていないPromise
が存在する場合、このイベントが発火されます。
addEventListener("unhandledrejection", (event) => {
console.error(event.reason); // error: Uncaught (in promise) Error: foo
});
Promise.reject(new Error("foo"));
Window: unhandledrejection event
"beforeunload"
イベントがサポート
Denoのイベントループが停止される直前に発火されます。
また、"beforeunload"
のリスナ内で.preventDefault()
を呼ぶとイベントループが再開されるため、改めてsetTimeout()
などの非同期処理を呼ぶことが出来ます。
let called = false;
addEventListener("beforeunload", (event) => {
if (!called) {
called = true;
event.preventDefault();
setTimeout(() => {
console.log(3);
}, 50);
}
});
setTimeout(() => {
console.log(1);
setTimeout(() => {
console.log(2);
}, 200);
}, 100);
// Output:
// 1
// 2
// 3
deno.json(c)
でdeno test
がカスタマイズできるように
deno lint
やdeno fmt
などと同様に、deno.json(c)
でdeno test
によるテスト対象をカスタマイズできるようになりました。
例えば、下記のように設定しておくと、vendor
ディレクトリ配下のテストコードが実行されなくなります。
{
"test": {
"files": {
"exclude": ["vendor"]
}
}
}
deno test
コマンドの実行時にテスト対象ファイルや--ignore
オプションが指定された際は、そちらがdeno.json(c)
の設定内容よりも優先されます。
cli/schemas/config-file.v1.json#L325-L349
deno test
で--parallel
オプションがサポート
挙動としては、既存の--jobs
オプションと同様に、テストを並列実行したい場合に利用します。
$ DENO_JOBS=4 deno test --parallel
既存の--jobs
との違いとして、テスト実行の並列数を指定したい場合は、オプション引数ではなくDENO_JOBS
環境変数に指定する必要があります。
--parallel
の導入に伴い、--jobs
は非推奨化されています。
dneo lsp
の改善
import-map-remap
コードアクションがサポート
Import mapsファイルで指定されたマッピング情報を元に、import指定子を更新してくれます。
例えば、下記のようなImport mapsファイルがあったとします。
{
"imports": {
"preact": "https://esm.sh/preact@10.8.1"
}
}
次に、下記のようなコードがあったとします。
import { render } from "https://esm.sh/preact@10.8.1";
上記のimportに対してimport-map-remap
アクションを実行すると、下記のように、Import mapsファイルで指定された内容へ変換されます。
import { render } from "preact";
その他の改善点
checkJs
オプションが有効化されている際に、@deno-types
などによってjsファイルから参照されているtsファイルが存在する場合に、プロセスがパニックする問題が修正されています。deno repl
でimport指定子が空の状態でタブ補完をしようとすると、プロセスがパニックする問題が修正されています。deno task
に--cwd
オプションを指定した際に、そこで指定されたディレクトリではなく、カレントディレクトリのdeno.json
が読まれてしまう問題が修正されています。