跳至主要内容
Deno 2 终于来了 🎉️
了解更多
Deno 1.36

Deno 1.36:更灵活的安全性和扩展的测试 API

Deno 设计目标的核心是灵活且强大的运行时安全性。借助 Deno 1.36,我们使用 `--deny-*` 标志进一步扩展了您的安全选项。除了现有的 `--allow-*` 标志外,您现在还可以为网络通信、文件系统访问和其他潜在的敏感 API 配置允许列表和拒绝列表。

除了这些安全功能外,您还将在 1.36 中找到改进的测试和基准测试 API、更强大的 Node.js 和 npm 包支持、语言服务器改进等等。

如果您已安装 Deno,您可以在终端中使用以下命令将 Deno 升级到 1.36 版本

deno upgrade

继续阅读以了解更多有关 Deno 1.36 中提供的最新功能和修复的信息!

Deno 1.36 概述

  • 🔐 Deno 程序的更灵活的安全选项 使用 `--deny-*` 标志在运行时保护您的程序,这些标志使您可以为应限制访问的域、文件路径和其他资源配置拒绝列表。
  • 🧪 测试和基准测试的扩展选项 新的测试结果格式化程序、对 Node.js 测试 API 的支持以及更细粒度的基准测试。
  • Node.js 兼容性改进 运行未配置为二进制文件的 npm 包脚本,使用我们最新的 polyfill 使用所有 `node:os` API,使用 `process.dlopen` 调用本机代码附加组件等等。
  • 🏝️ 生活质量改进 诸如更好的错误消息、语言服务器改进以及更宽容的 WebSocket API 等小功能和修复。
  • 🙏 开源社区贡献 没有社区的支持,我们就无法构建 Deno!这些是核心团队之外的优秀人士,他们为 Deno 1.36 做出了贡献。

Deno 程序的更灵活的安全选项

Deno 运行时默认提供安全性,使开发人员能够选择加入,以允许其代码和依赖项使用 `--allow-*` CLI 标志进行网络请求、访问文件系统或使用其他潜在的危险 API。

这些选项有用且依然有用,但在某些情况下有点不灵活。您可以为您的程序提供对给定功能的无限制访问权限,或者您需要配置 `--allow-*` 选项将启用的特定域或目录。没有办法只排除一些域或文件路径来打开沙箱。在 Deno 1.36 中,我们引入了 `--deny-*` 运行时标志系列,以使您的 Deno 程序的权限更加灵活。

例如,如果您希望您的程序可以访问任何它想要的 URL,但排除一些特定的 IP 地址和域,您可以使用

$ deno run --allow-net --deny-net=api.evil.com mod.ts

例如,如果您想让您的程序访问整个文件系统,但排除 `/etc` 目录

$ deno run --allow-read --deny-read=/etc --allow-write --deny-write=/etc mod.ts

之前具有 `--allow-*` 选项的每个 CLI 标志现在也将具有相应的 `--deny-*` 选项。拒绝标志的优先级高于允许标志,因此如果您在同一域或文件路径上同时使用两者,访问仍将被拒绝

$ deno run --allow-read=foo.txt --deny-read=foo.txt mod.ts
error: PermissionDenied: Requires read access to "foo.txt"...

在此,我们要特别感谢Asher GomezNayeem Rahman,他们领导了这项新功能的实施。非常感谢您的贡献!

我们打算在将来进一步改进和扩展权限系统的功能。我们正在考虑实施的功能之一是能够从配置文件中使用预定义的权限 - 关注此问题以获取更新。

我们很乐意听取您对新的 `--deny-*` 标志以及您对权限系统相关的任何其他需求的反馈。请在Discord 上告诉我们,在我们的一场直播活动中(也位于 Discord 上),或者通过在 GitHub 上提出问题

测试和基准测试的扩展选项

Deno 1.36 还引入了对应用程序中的测试和基准测试的改进。在测试方面,您现在可以使用新的自定义格式化程序输出 `deno test` 运行的结果。

JUnit 报告器

拥有机器可读的测试报告对于测试的自动化质量保证和大型代码库的可维护性至关重要。JUnit XML 格式可以被许多服务(如 GitLab、CircleCI、Jenkins 或 BuildPulse)原生使用。从 Deno 1.36 开始,您可以将 `--reporter=junit` 标志传递给 `deno test` 以获取结构化报告数据

# Print a JUnit report to the terminal so you can process it further…
$ deno test --reporter=junit

# …or write it directly to a file alongside the default human-readable output.
 deno test --junit-path=test_report.xml

点报告器

对于那些喜欢简短而甜蜜的测试报告的人,我们添加了一个 `dot` 报告器,它提供了简洁的输出,消除了很多噪音。

deno test --reporter=dot

node:test polyfill

如果您是从 Node.js 的最新版本迁移到 Deno,除了`Deno.test`标准库中的 `describe`/`it` API 外,您现在还可以使用 Node 20 中内置的测试 API。

使用以下简单测试工具在 Deno 中自己尝试一下。

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

test("synchronous passing test", (t) => {
  // This test passes because it does not throw an exception.
  assert.strictEqual(1, 1);
});

test("asynchronous passing test", async (t) => {
  // This test passes because the Promise returned by the async
  // function is not rejected.
  assert.strictEqual(1, 1);
});

并非所有 API 表面区域都被覆盖,因此如果您遇到问题,我们将非常感谢您提交错误报告

deno bench 改进

通过向 `Deno.bench` 添加新功能,Deno 中的基准测试粒度和精度得到了改进。

在 Deno 的早期版本中,`Deno.bench` 函数由于一种称为“JIT 偏差”的现象而对第一个运行的基准案例产生了令人惊讶的结果 - V8 引擎对基准函数进行了过度优化,然后在后续函数上放弃了优化,导致结果不具有代表性。现在已通过在用户定义的基准案例之前运行一个“预热”函数来修复此问题。

此外,您现在可以使用 `Deno.BenchContext.start` 和 `Deno.BenchContext.end` 来告诉基准测试工具您要测量的关键部分。在两次调用之间的部分之外的所有内容都将从测量中排除。

import { readAll } from "https://deno.land/[email protected]/streams/mod.ts";

Deno.bench("foo", async (b) => {
  // Open a file that we will act upon.
  const file = await Deno.open("a_big_data_file.txt");

  // Tell the benchmarking tool that this is the only section you want
  // to measure.
  b.start();

  // Now let's measure how long it takes to read all of the data from the file.
  await readAll(file);

  // End measurement here.
  b.end();

  // Now we can perform some potentially time-consuming teardown that will not
  // taint out benchmark results.
  file.close();
});

我们还更新了 `deno bench` 输出,以包含有关每秒迭代的信息

Output from deno bench showing iter/s column

Node.js 兼容性改进

运行未配置为二进制文件的 npm 脚本

您现在可以运行来自 npm 包的脚本,这些脚本未在包的`package.json` 中的 `bin` 属性中配置。示例

deno run -A npm:[email protected]/foo/cli.mjs

process.dlopen 可用

你现在可以使用 process.dlopen API 来加载 Node.js 的原生插件。

AsyncLocalStorage 速度提高了 3.5 倍

我们优化了 AsyncLocalStorage(来自 node:async_hooks 模块)的实现。我们的基准测试表明,它比 Deno v1.35.3 快了 3.5 倍。

node:os 完全填充

Node.js os 模块getPrioritysetPriorityuserInfo 函数现在可用,这使得 node:os 模块完全填充。

了解有关在 Deno 手册中使用 Node.js 内置函数的更多信息

示例

import { getPriority } from "node:os";

console.log(getPriority());

生活质量改进

下面,我们列出了一些其他功能和错误修复,这些功能和错误修复已包含在该版本中,我们认为这些功能和错误修复会对您日常工作产生重大影响。

deno compile --no-terminal

现在可以使用新的 --no-terminal 标志与 deno compile 一起使用。如果编译后的二进制文件在 Windows 上运行,此标志将阻止打开终端窗口。

Deno.createHttpClient.allowHost

不稳定的 Deno.createHttpClient 现在支持 allowHost 选项,可以为 fetch 请求指定 Host 标头。

const client = Deno.createHttpClient({
  allowHost: true,
});
const res = await fetch("http://example.com", {
  headers: {
    "host": "myhost.com",
  },
  client,
});

WebSocket API 中允许 HTTP(S) URL

你现在可以在 WebSocket Web API 中使用 http:https: URL,Deno 会自动将协议调整为分别使用 ws:wss:

const url = new URL("https://example.com");
const ws = new WebSocket(url);
console.log(ws.url);
// wss://example.com

重试失败的模块下载

Deno 在下载依赖项时现在更加健壮。由于间歇性连接问题或远程服务器上的随机错误,连接到远程主机总是可能失败。

在这种情况下,Deno 会等待一小段时间并重试下载,从而使 CI 管道更加可靠,并减少重新运行命令的需要。

Deno.Command API 中更实用的错误

在 1.36 之前,如果你尝试使用 Deno.Command 为不存在的二进制文件生成子进程,你会看到一个没有帮助的错误消息

$ deno
> new Deno.Command("this-binary-does-not-exist").spawn();
Uncaught NotFound: No such file or directory (os error 2)
    at spawnChildInner (ext:runtime/40_process.js:162:17)
    at spawnChild (ext:runtime/40_process.js:182:10)
    at Command.spawn (ext:runtime/40_process.js:440:12)
    at <anonymous>:2:48

使用 Deno 1.36,错误消息将包含未找到的二进制文件的名称

$ deno
> new Deno.Command("this-binary-does-not-exist").spawn();
Uncaught NotFound: Failed to spawn: this-binary-does-not-exist: No such file or directory (os error 2)
    at spawnChildInner (ext:runtime/40_process.js:162:17)
    at spawnChild (ext:runtime/40_process.js:182:10)
    at Command.spawn (ext:runtime/40_process.js:440:12)
    at <anonymous>:2:48

LSP 改进

Deno 1.36 包含对 LSP 的大量修复和改进。这应该会使 Deno 与支持 LSP 的编辑器(如 Visual Studio Code)一起使用变得更加愉快。以下是一些更改

还想了解更多?

信不信由你,上面列出的更改仍然没有告诉你 1.36 中所有改进。你可以查看合并到 Deno 1.36 中的完整拉取请求列表 在 GitHub 上查看

感谢社区贡献者!

如果没有社区的帮助,我们无法构建 Deno!无论是通过在社区 Discord 服务器 中回答问题,还是 报告错误,我们都非常感谢你们的支持。特别是,我们要感谢以下为 Deno 1.36 做出贡献的人。

你想加入 Deno 社区贡献者的行列吗? 在这里查看我们的贡献文档,我们下次在列表中见到你。

感谢您关注我们的 1.36 版本,我们希望您喜欢使用 Deno 进行构建!

🍋 你知道吗?Fresh 变得更清新了。

一定要查看 Fresh 1.3 的发布说明,这是 Deno 的下一代网络框架的最新版本。