Spec-Zone.ru › Deno 2

API веб-платформы

Один из способов, которыми Deno упрощает разработку для веба и облака, — использование стандартных API веб-платформы (например, fetch, WebSockets и других) вместо проприетарных API. Это означает, что если вы когда-либо разрабатывали приложения для браузера, то, скорее всего, уже знакомы с Deno, а если вы изучаете Deno, то одновременно расширяете свои знания о вебе.

Посмотреть поддерживаемые API веб-платформы

Ниже мы расскажем о некоторых стандартных API веб-платформы, поддерживаемых Deno.

Чтобы проверить, доступен ли API веб-платформы в Deno, можно нажать на интерфейс на MDN и посмотреть таблицу совместимости с браузерами.

fetch

API fetch можно использовать для выполнения HTTP-запросов. Он реализован в соответствии со спецификацией WHATWG fetch.

Отклонения от спецификации

  • В пользовательском агенте Deno нет хранилища cookie. Поэтому заголовок set-cookie в ответе не обрабатывается и не удаляется из видимых заголовков ответа.
  • Deno не соблюдает политику одного источника, поскольку в пользовательском агенте Deno в настоящее время отсутствует понятие источников и нет хранилища cookie. Это означает, что Deno не нужно защищаться от утечки аутентифицированных данных между источниками. Поэтому Deno не реализует следующие разделы спецификации WHATWG fetch:
    • Раздел 3.1. 'Origin' header.
    • Раздел 3.2. CORS protocol.
    • Раздел 3.5. CORB.
    • Раздел 3.6. 'Cross-Origin-Resource-Policy' header.
    • Atomic HTTP redirect handling.
    • Тип ответа opaqueredirect.
  • Для fetch с режимом redirect, равным manual, возвращается ответ basic, а не ответ opaqueredirect.
  • В спецификации неясно, как следует обрабатывать URL file:. Firefox — единственный широко распространённый браузер, поддерживающий получение данных по URL file:, и даже в нём эта возможность по умолчанию не работает. Начиная с Deno 1.16, Deno поддерживает получение данных из локальных файлов. Подробности см. в следующем разделе.
  • Защита заголовков request и response реализована, но, в отличие от браузеров, не ограничивает допустимые имена заголовков.
  • Свойства referrer, referrerPolicy, mode, credentials, cache, integrity, keepalive и window, а также связанное с ними поведение в RequestInit не реализованы. Соответствующие поля отсутствуют в объекте Request.
  • Член priority объекта RequestInit ("auto", "high" или "low") принимается и проверяется. Согласно стандарту Fetch, это свойство доступно только для записи, поэтому оно не отображается как свойство объекта Request.
  • Поддерживается потоковая передача тела запроса (для HTTP/1.1 и HTTP/2). В отличие от текущего предложения по Fetch, реализация поддерживает двунаправленную потоковую передачу.
  • Заголовок set-cookie не объединяется при переборе итератора headers. Это поведение сейчас проходит процесс стандартизации.

Получение локальных файлов

Deno поддерживает получение данных по URL file:. Это упрощает написание кода, который использует один и тот же путь выполнения и на сервере, и локально, а также создание кода, работающего как с Deno CLI, так и с Deno Deploy.

Deno поддерживает только абсолютные URL файлов, поэтому fetch("./some.json") работать не будет. Однако следует учесть, что если указан --location, то относительные URL используют --location в качестве базового, но URL file: нельзя передать как --location.

Чтобы получить ресурс относительно текущего модуля, независимо от того, локальный он или удалённый, используйте import.meta.url в качестве базового URL. Например:

const response = await fetch(new URL("./config.json", import.meta.url));
const config = await response.json();

Примечания о получении локальных файлов:

  • При чтении ресурсов применяются разрешения, поэтому для чтения локального файла требуется соответствующее разрешение --allow-read.
  • Для локального получения данных поддерживается только метод GET; при использовании любого другого метода промис будет отклонён.
  • Если файл не существует, промис отклоняется с неопределённой ошибкой TypeError. Это позволяет избежать потенциальных атак с целью снятия отпечатка.
  • В ответе не устанавливаются заголовки. Поэтому определять такие параметры, как тип или длина содержимого, должен вызывающий код.
  • Тела ответов передаются потоком со стороны Rust, поэтому большие файлы доступны по частям, а передачу можно отменить.

Структурное клонирование и передаваемые объекты

Deno поддерживает structuredClone() и postMessage() для клонирования и передачи объектов между контекстами (например, между главным потоком и веб-воркерами).

Сериализуемые типы

Эти типы можно клонировать с помощью structuredClone() и передавать через postMessage():

Тип Примечания
Примитивы string, number, boolean, null, undefined, bigint
Array, Object, Map, Set Включая вложенные структуры и циклические ссылки
Date, RegExp
ArrayBuffer, TypedArray, DataView По умолчанию копируются или передаются (см. ниже)
типы Error Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError
Blob Требуется Deno 2.8 или новее
File Требуется Deno 2.8 или новее
DOMException
CryptoKey

Передаваемые типы

Эти типы можно передавать (не копировать) с помощью параметра transfer в structuredClone() или списка transfer в postMessage(). После передачи исходный объект становится непригодным для использования:

Тип Примечания
ArrayBuffer Перемещает базовую память получателю
MessagePort Передаёт порт в другой контекст
ReadableStream Передаёт поток в другой контекст
WritableStream Передаёт поток в другой контекст
TransformStream Передаёт поток в другой контекст
// Clone a Blob
const blob = new Blob(["hello"], { type: "text/plain" });
const cloned = structuredClone(blob);
console.log(await cloned.text()); // "hello"

// Transfer an ArrayBuffer through a MessageChannel
const buffer = new ArrayBuffer(1024);
const ch = new MessageChannel();
ch.port1.postMessage(buffer, [buffer]);
// buffer.byteLength is now 0 (transferred)

CustomEvent и EventTarget

API событий DOM можно использовать для отправки событий, происходящих в приложении, и прослушивания таких событий. Он реализован в соответствии со спецификацией WHATWG DOM.

Отклонения от спецификации

  • События не всплывают, поскольку в Deno нет иерархии DOM и, следовательно, дерева, по которому события могли бы всплывать или перехватываться.
  • Свойству timeStamp всегда присваивается значение 0.

Типы

Определения TypeScript для реализованных веб-API находятся в файлах lib.deno.shared_globals.d.ts и lib.deno.window.d.ts.

Определения, относящиеся к воркерам, находятся в файле lib.deno.worker.d.ts.

Location

Deno поддерживает глобальный объект location из веб-платформы.

Флаг location

В процессе Deno нет «веб-страницы», URL которой можно было бы использовать для определения местоположения. Вместо этого пользователи могут эмулировать местоположение документа, указав его в CLI с помощью флага --location. Это может быть URL http или https.

// deno run --location https://example.com/path main.ts

console.log(location.href);
// "https://example.com/path"

Для работы необходимо передать --location <href>. Если этого не сделать, любое обращение к глобальному объекту location вызовет ошибку.

// deno run main.ts

console.log(location.href);
// error: Uncaught ReferenceError: Access to "location", run again with --location <href>.

Изменение location или любого из его полей обычно вызывает переход в браузерах. В Deno это неприменимо, поэтому в такой ситуации будет выброшена ошибка.

// deno run --location https://example.com/path main.ts

location.pathname = "./foo";
// error: Uncaught NotSupportedError: Cannot set "location.pathname".

Расширенное использование

В вебе при разрешении ресурсов (за исключением модулей) обычно используется значение location.href в качестве основы для всех относительных URL. Это влияет на некоторые API веб-платформы, используемые в Deno.

API Fetch

// deno run --location https://api.github.com/ --allow-net main.ts

const response = await fetch("./orgs/denoland");
// Fetches "https://api.github.com/orgs/denoland".

Вызов fetch() выше вызовет ошибку, если флаг --location не был передан, поскольку в Deno нет аналога местоположения веб-страницы, относительно которого можно было бы выполнить разрешение URL.

Модули воркеров

// deno run --location https://example.com/index.html --allow-net main.ts

const worker = new Worker("./workers/hello.ts", { type: "module" });
// Fetches worker module at "https://example.com/workers/hello.ts".
Примечание

В приведённых выше случаях предпочтительнее передавать полные URL, а не полагаться на --location. При необходимости относительный URL можно вручную задать относительно базового с помощью конструктора URL.

Флаг --location предназначен для тех, кому необходимо эмулировать местоположение документа и кто понимает, что это будет работать только на уровне приложения. Однако его также можно использовать, чтобы подавить ошибки, вызванные зависимостью, которая без необходимости обращается к глобальному объекту location.

Веб-хранилище

API веб-хранилища предоставляет средства для хранения строковых ключей и значений. Сохранение данных работает аналогично браузерному и имеет ограничение в 10 МБ. Глобальный объект sessionStorage сохраняет данные только в текущем контексте выполнения, а localStorage сохраняет данные между запусками.

В браузере localStorage сохраняет данные отдельно для каждого источника (фактически сочетания протокола, имени хоста и порта). Начиная с Deno 1.16, Deno использует набор правил для определения уникального расположения хранилища:

  • При использовании флага --location для уникального хранения данных используется источник местоположения. Это означает, что местоположения http://example.com/a.ts, http://example.com/b.ts и http://example.com:80/ будут использовать одно хранилище, а https://example.com/ — другое.
  • Если местоположение не указано, но указан файл конфигурации --config, используется абсолютный путь к этому файлу. Это означает, что deno run --config deno.jsonc a.ts и deno run --config deno.jsonc b.ts будут использовать одно хранилище, а deno run --config tsconfig.json a.ts — другое.
  • Если конфигурация и местоположение не указаны, Deno использует абсолютный путь к главному модулю, чтобы определить, какие данные хранилища являются общими. REPL Deno создаёт «синтетический» главный модуль, основанный на текущем рабочем каталоге, из которого запущен deno. Это означает, что несколько запусков REPL из одного каталога будут совместно использовать сохранённые данные localStorage.

Для добавления, получения и удаления элементов в localStorage используйте следующий код:

// Set an item in localStorage
localStorage.setItem("myDemo", "Deno App");

// Read an item from localStorage
const cat = localStorage.getItem("myDemo");

// Remove an item from localStorage
localStorage.removeItem("myDemo");

// Remove all items from localStorage
localStorage.clear();

Веб-воркеры

Deno поддерживает Web Worker API.

Воркеры можно использовать для выполнения кода в нескольких потоках. Каждый экземпляр Worker выполняется в отдельном потоке, выделенном только этому воркеру.

В настоящее время Deno поддерживает только воркеры типа module, поэтому при создании нового воркера обязательно нужно передать параметр type: "module".

Использование относительных спецификаторов модулей в главном воркере поддерживается только при передаче --location <href> в CLI. Для переносимости такой способ не рекомендуется. Вместо этого можно использовать конструктор URL и import.meta.url, чтобы легко создать спецификатор для ближайшего скрипта. Однако выделенные воркеры по умолчанию имеют местоположение и поддерживают эту возможность.

// Good
new Worker(import.meta.resolve("./worker.js"), { type: "module" });

// Bad
new Worker(import.meta.resolve("./worker.js"));
new Worker(import.meta.resolve("./worker.js"), { type: "classic" });
new Worker("./worker.js", { type: "module" });

Как и в обычных модулях, в модулях воркеров можно использовать await верхнего уровня. Однако всегда регистрируйте обработчик сообщений до первого await, иначе сообщения могут быть потеряны. Это не ошибка Deno, а лишь неприятное взаимодействие особенностей платформы; такое же поведение наблюдается во всех браузерах, поддерживающих модульные воркеры.

import { delay } from "jsr:@std/async@1/delay";

// First await: waits for a second, then continues running the module.
await delay(1000);

// The message handler is only set after that 1s delay, so some of the messages
// that reached the worker during that second might have been fired when no
// handler was registered.
self.onmessage = (evt) => {
  console.log(evt.data);
};

Отправка сообщений в главный поток

Обмен данными происходит в обоих направлениях. Главный поток отправляет данные воркеру с помощью worker.postMessage() и ожидает ответы с помощью worker.onmessage. Внутри воркера self.onmessage получает сообщения, а self.postMessage() отправляет результаты обратно:

main.ts
const worker = new Worker(import.meta.resolve("./worker.ts"), {
  type: "module",
});

// Receive results from the worker
worker.onmessage = (evt) => {
  console.log("result from worker:", evt.data);
};

// Send work to the worker
worker.postMessage(41);
worker.ts
self.onmessage = (evt) => {
  const result = evt.data + 1;
  // Send the result back to the main thread
  self.postMessage(result);
};

Запуск deno run --allow-read main.ts выводит result from worker: 42.

Разрешения при создании экземпляра

Создание экземпляра Worker аналогично динамическому импорту, поэтому для этого действия Deno требует соответствующее разрешение.

Для воркеров, использующих локальные модули, требуется разрешение --allow-read:

main.ts
new Worker(import.meta.resolve("./worker.ts"), { type: "module" });
worker.ts
console.log("hello world");
self.close();
$ deno run main.ts
error: Uncaught PermissionDenied: read access to "./worker.ts", run again with the --allow-read flag

$ deno run --allow-read main.ts
hello world

Для воркеров, использующих удалённые модули, требуется разрешение --allow-net:

main.ts
new Worker("https://example.com/worker.ts", { type: "module" });
worker.ts
// This file is hosted at https://example.com/worker.ts
console.log("hello world");
self.close();
$ deno run main.ts
error: Uncaught PermissionDenied: net access to "https://example.com/worker.ts", run again with the --allow-net flag

$ deno run --allow-net main.ts
hello world

Использование Deno в воркере

main.js
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
});

worker.postMessage({ filename: "./log.txt" });
worker.js
self.onmessage = async (e) => {
  const { filename } = e.data;
  const text = await Deno.readTextFile(filename);
  console.log(text);
  self.close();
};
log.txt
hello world
$ deno run --allow-read main.js
hello world

Указание разрешений воркера

Внимание

Эта функция Deno нестабильна. Подробнее см. описание нестабильных функций.

Доступные воркеру разрешения аналогичны флагам разрешений CLI: любое разрешение, включённое там, можно отключить на уровне API Worker. Более подробное описание каждого параметра разрешений приведено здесь.

По умолчанию воркер наследует разрешения потока, в котором он был создан. Однако, чтобы пользователи могли ограничивать доступ воркера, в API Worker предусмотрен параметр deno.permissions.

Для разрешений, допускающих детальную настройку доступа, можно передать список ресурсов, к которым воркер получит доступ. Для разрешений, которые можно только включить или выключить, можно передать соответственно true или false:

const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: {
      net: [
        "deno.land",
      ],
      read: [
        new URL("./file_1.txt", import.meta.url),
        new URL("./file_2.txt", import.meta.url),
      ],
      write: false,
    },
  },
});

Для разрешений с детальной настройкой доступа в качестве аргументов принимаются как абсолютные, так и относительные пути. Учтите, что относительные пути разрешаются относительно файла, в котором создаётся воркер, а не относительно каталога, в котором находится файл воркера:

const worker = new Worker(
  new URL("./worker/worker.js", import.meta.url).href,
  {
    type: "module",
    deno: {
      permissions: {
        read: [
          "/home/user/Documents/deno/worker/file_1.txt",
          "./worker/file_2.txt",
        ],
      },
    },
  },
);

И deno.permissions, и его дочерние элементы поддерживают параметр "inherit", который означает, что воркер наследует разрешения родительского объекта:

// This worker will inherit its parent permissions
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: "inherit",
  },
});
// This worker will inherit only the net permissions of its parent
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: {
      env: false,
      hrtime: false,
      net: "inherit",
      ffi: false,
      read: false,
      run: false,
      write: false,
    },
  },
});

Если не указать параметр deno.permissions или один из его дочерних элементов, воркер по умолчанию унаследует разрешения:

// This worker will inherit its parent permissions
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
});
// This worker will inherit all the permissions of its parent BUT net
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: {
      net: false,
    },
  },
});

Можно полностью отключить разрешения воркера, передав "none" параметру deno.permissions:

// This worker will not have any permissions enabled
const worker = new Worker(import.meta.resolve("./worker.js"), {
  type: "module",
  deno: {
    permissions: "none",
  },
});

OffscreenCanvas

Начиная с Deno 2.8 доступен API OffscreenCanvas. OffscreenCanvas — это холст, существующий вне DOM и доступный в любом месте (в том числе в веб-воркерах) для отрисовки и создания изображений в отдельном потоке.

Поддерживаемые контексты отрисовки

OffscreenCanvas#getContext принимает два идентификатора контекста, определённых спецификацией:

  • "bitmaprenderer": возвращает ImageBitmapRenderingContext для отображения ImageBitmap, созданного с помощью createImageBitmap.
  • "webgpu": возвращает GPUCanvasContext для отрисовки с помощью WebGPU.

Вызов getContext с аргументом "2d", "webgl" или "webgl2" возвращает null; эти контексты в Deno не реализованы.

Пример: кодирование изображения в PNG

Декодируйте изображение в ImageBitmap, поместите его на OffscreenCanvas с помощью контекста bitmaprenderer и запишите результат на диск:

const data = await Deno.readFile("./input.jpg");
const bitmap = await createImageBitmap(new Blob([data]));

const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
const ctx = canvas.getContext("bitmaprenderer")!;
ctx.transferFromImageBitmap(bitmap);

const blob = await canvas.convertToBlob({ type: "image/png" });
await Deno.writeFile(
  "./output.png",
  new Uint8Array(await blob.arrayBuffer()),
);

Типичные сценарии использования:

  • создание миниатюр, преобразование форматов или изображений для карточек публикаций во время обработки запроса без запуска безголового браузера;
  • обработка изображений в отдельном потоке внутри веб-воркера;
  • управление целями отрисовки WebGPU, которым не требуется окно.

Геометрические интерфейсы

Начиная с Deno 2.8 типы из Geometry Interfaces Module Level 1 доступны как глобальные объекты. Это те же типы, что и в браузерах:

  • DOMMatrix / DOMMatrixReadOnly: матрицы преобразования 4×4 для двумерных и трёхмерных операций.
  • DOMPoint / DOMPointReadOnly: точки в двумерном и трёхмерном пространстве.
  • DOMRect / DOMRectReadOnly: прямоугольники, выровненные по осям.
  • DOMQuad: четырёхугольник, заданный четырьмя точками.
const m = new DOMMatrix().translateSelf(10, 20).scaleSelf(2);
const p = new DOMPoint(1, 1).matrixTransform(m);
console.log(p.x, p.y); // 12 22

Эти типы полезны при работе с графикой: для применения преобразований к рисункам на холсте, вычисления геометрии макета или переноса браузерного кода, зависящего от геометрических типов.

navigator

Deno реализует подмножество глобального объекта navigator. Доступны следующие свойства:

  • navigator.userAgent — всегда "Deno/<version>"
  • navigator.platform — платформа базовой ОС (например, "Linux x86_64", "MacIntel", "Win32"). Добавлено в Deno 2.7.
  • navigator.hardwareConcurrency — количество логических ядер ЦП
  • navigator.userAgentData — объект NavigatorUAData, реализующий API User-Agent Client Hints. Свойства с низкой энтропией brands, mobile и platform считываются синхронно, а getHighEntropyValues(hints) разрешается с дополнительными сведениями, такими как architecture, model и platformVersion.
  • navigator.locks — объект LockManager, реализующий API Web Locks для координации доступа к именованному ресурсу с помощью navigator.locks.request() и navigator.locks.query().
console.log(navigator.userAgent); // "Deno/2.7.0"
console.log(navigator.platform); // e.g. "Linux x86_64", "MacIntel", "Win32"
console.log(navigator.hardwareConcurrency); // e.g. 8
console.log(navigator.userAgentData.brands); // e.g. [{ brand: "Deno", version: "2" }]

Temporal

API Temporal — это современная библиотека для работы с датой и временем, которая заменяет Date в большинстве случаев. В Deno 2.7 она получила стабильный статус и доступна как глобальный объект без каких-либо флагов.

// Current date/time in local timezone
const now = Temporal.Now.plainDateTimeISO();
console.log(now.toString()); // e.g. "2025-03-12T10:30:00"

// Parse a date
const date = Temporal.PlainDate.from("2025-03-12");
console.log(date.month); // 3

// Timezone-aware
const zonedNow = Temporal.Now.zonedDateTimeISO("America/New_York");
console.log(zonedNow.timeZoneId); // "America/New_York"

До выхода Deno 2.7 для Temporal требовался флаг --unstable-temporal.

CompressionStream и DecompressionStream

Deno поддерживает CompressionStream и DecompressionStream для потокового сжатия и распаковки.

Поддерживаемые форматы

Формат Строка Примечания
gzip "gzip" RFC 1952
deflate "deflate" zlib (RFC 1950)
deflate-raw "deflate-raw" сырой DEFLATE (1951)
Brotli "brotli" Добавлено в Deno 2.7
// Compress with Brotli
const input = new TextEncoder().encode("Hello, Deno!");
const cs = new CompressionStream("brotli");
const writer = cs.writable.getWriter();
writer.write(input);
writer.close();
const compressed = await new Response(cs.readable).arrayBuffer();

// Decompress
const ds = new DecompressionStream("brotli");
const writer2 = ds.writable.getWriter();
writer2.write(new Uint8Array(compressed));
writer2.close();
const result = await new Response(ds.readable).text();
console.log(result); // "Hello, Deno!"

Web Crypto

Deno поддерживает API Web Crypto через crypto.subtle.

Обнаружение возможностей

SubtleCrypto.supports() — это статический метод для синхронной проверки доступности заданной комбинации алгоритма и операции без выполнения операции и перехвата ошибки. Он принимает имя операции, алгоритм и необязательный третий аргумент и возвращает логическое значение. Добавлено в Deno 2.9.

SubtleCrypto.supports("digest", "SHA3-256"); // true
SubtleCrypto.supports("generateKey", "ChaCha20-Poly1305"); // true
SubtleCrypto.supports("sign", "ML-DSA-65"); // true

Операция должна быть одной из следующих: "encrypt", "decrypt", "sign", "verify", "digest", "generateKey", "deriveKey", "deriveBits", "importKey", "exportKey", "wrapKey", "unwrapKey", "encapsulateKey", "encapsulateBits", "decapsulateKey", "decapsulateBits" или "getPublicKey".

Назначение необязательного третьего аргумента зависит от операции: для "deriveBits" это длина в битах, а в остальных случаях — связанный алгоритм, например алгоритм производного ключа для "deriveKey" или алгоритм общего ключа для "encapsulateKey" и "decapsulateKey".

// Will deriveKey produce an AES-GCM key from HKDF?
SubtleCrypto.supports("deriveKey", "HKDF", { name: "AES-GCM", length: 256 });

SubtleCrypto.supports() входит в черновик WICG «Современные алгоритмы в API Web Cryptography».

Хеш-алгоритмы SHA-3

Начиная с Deno 2.7 семейство хеш-алгоритмов SHA-3 поддерживается в crypto.subtle.digest:

  • SHA3-256
  • SHA3-384
  • SHA3-512
const data = new TextEncoder().encode("Hello, Deno!");
const hash = await crypto.subtle.digest("SHA3-256", data);
console.log(new Uint8Array(hash));

Для ключа HMAC также можно использовать хеш SHA-3. При создании или импорте ключа передайте имя алгоритма в качестве hash:

const key = await crypto.subtle.generateKey(
  { name: "HMAC", hash: "SHA3-256" },
  true,
  ["sign", "verify"],
);
const signature = await crypto.subtle.sign("HMAC", key, data);

Функции с расширяемым выходом

В Deno 2.9 добавлена поддержка функций с расширяемым выходом (XOF) SHAKE, cSHAKE, TurboSHAKE и KangarooTwelve. В отличие от хеша фиксированного размера, XOF может создавать дайджест произвольной длины, поэтому для crypto.subtle.digest требуется параметр outputLength, задающий размер выходных данных в битах. Значение outputLength должно быть положительным числом, кратным 8. Поддерживаются следующие имена:

  • SHAKE128, SHAKE256
  • cSHAKE128, cSHAKE256
  • TurboSHAKE128, TurboSHAKE256
  • KT128 (также принимается KangarooTwelve) и KT256
const data = new TextEncoder().encode("Hello, Deno!");

// 256-bit (32-byte) SHAKE256 digest.
const digest = await crypto.subtle.digest(
  { name: "SHAKE256", outputLength: 256 },
  data,
);
console.log(new Uint8Array(digest).length); // 32

cSHAKE128 и cSHAKE256 принимают два необязательных параметра BufferSource для настройки функции: functionName — имя функции, определённое NIST, и customization — строка разделения доменов, задаваемая вызывающим кодом.

const digest = await crypto.subtle.digest(
  {
    name: "cSHAKE128",
    outputLength: 256,
    customization: new TextEncoder().encode("my-app"),
  },
  data,
);

TurboSHAKE128 и TurboSHAKE256 принимают необязательный байт domainSeparation, который должен находиться в диапазоне от 0x01 до 0x7F:

const digest = await crypto.subtle.digest(
  { name: "TurboSHAKE256", outputLength: 512, domainSeparation: 0x1f },
  data,
);

KT128 и KT256 — это XOF-функции KangarooTwelve. Они принимают необязательный параметр customization BufferSource:

const digest = await crypto.subtle.digest(
  { name: "KT128", outputLength: 256 },
  data,
);

KMAC

KMAC128 и KMAC256 — это коды аутентификации сообщений с ключом, основанные на cSHAKE. Добавлено в Deno 2.9. Создайте ключ, указав length в битах, затем подписывайте и проверяйте подпись, указав outputLength в битах и необязательный параметр customization BufferSource:

const key = await crypto.subtle.generateKey(
  { name: "KMAC128", length: 128 },
  true,
  ["sign", "verify"],
);

const data = new TextEncoder().encode("Hello, Deno!");
const params = {
  name: "KMAC128",
  outputLength: 256,
  customization: new TextEncoder().encode("Deno"),
};
const mac = await crypto.subtle.sign(params, key, data);
const valid = await crypto.subtle.verify(params, key, mac, data);

Ключи KMAC можно импортировать и экспортировать в форматах "raw", "raw-secret" и "jwk".

Argon2

Argon2d, Argon2i и Argon2id — это функции выработки ключа на основе пароля. Добавлено в Deno 2.9. Импортируйте пароль как ключ в формате "raw-secret" с назначением deriveBits, а затем вызовите deriveBits. Параметры: memory (затраты памяти в кибибайтах), passes (число итераций), parallelism (степень параллелизма) и nonce BufferSource (соль). Параметры secretValue и associatedData являются необязательными значениями BufferSource:

const password = new TextEncoder().encode("correct horse battery staple");
const key = await crypto.subtle.importKey(
  "raw-secret",
  password,
  "Argon2id",
  false,
  ["deriveBits"],
);

const derived = await crypto.subtle.deriveBits(
  {
    name: "Argon2id",
    memory: 65536,
    passes: 3,
    parallelism: 4,
    nonce: crypto.getRandomValues(new Uint8Array(16)),
  },
  key,
  256, // output length in bits
);

ChaCha20-Poly1305

Deno 2.9 поддерживает алгоритм аутентифицированного шифрования ChaCha20-Poly1305 с помощью generateKey, encrypt и decrypt. Длина ключей всегда составляет 256 бит:

const key = await crypto.subtle.generateKey(
  { name: "ChaCha20-Poly1305" },
  true,
  ["encrypt", "decrypt"],
);

Каждый вызов encrypt и decrypt принимает 12-байтовый nonce и необязательный additionalData, который проходит аутентификацию, но не шифруется. Для каждого сообщения, зашифрованного одним и тем же ключом, используйте новый nonce:

const nonce = crypto.getRandomValues(new Uint8Array(12));
const data = new TextEncoder().encode("Hello, Deno!");

const ciphertext = await crypto.subtle.encrypt(
  { name: "ChaCha20-Poly1305", nonce },
  key,
  data,
);

const plaintext = await crypto.subtle.decrypt(
  { name: "ChaCha20-Poly1305", nonce },
  key,
  ciphertext,
);
console.log(new TextDecoder().decode(plaintext)); // "Hello, Deno!"

Возвращаемый шифротекст включает 16-байтовый тег аутентификации Poly1305.

Постквантовая криптография

Deno 2.9 реализует постквантовые алгоритмы NIST из черновика WICG «Современные алгоритмы в API Web Cryptography»: подписи ML-DSA и SLH-DSA, а также инкапсуляцию ключей ML-KEM.

Подписи ML-DSA

ML-DSA (FIPS 204) — это основанная на решётках схема цифровой подписи. Доступны три набора параметров с возрастающим уровнем безопасности: ML-DSA-44, ML-DSA-65 и ML-DSA-87. Создайте пару ключей, затем подпишите сообщение закрытым ключом и проверьте подпись открытым ключом:

const { publicKey, privateKey } = await crypto.subtle.generateKey(
  { name: "ML-DSA-65" },
  true,
  ["sign", "verify"],
);

const data = new TextEncoder().encode("Hello, Deno!");
const signature = await crypto.subtle.sign(
  { name: "ML-DSA-65" },
  privateKey,
  data,
);
const valid = await crypto.subtle.verify(
  { name: "ML-DSA-65" },
  publicKey,
  signature,
  data,
);
console.log(valid); // true

sign и verify принимают необязательный context — BufferSource, привязывающий подпись к значению, специфичному для приложения. В обоих вызовах необходимо указать один и тот же context:

const context = new TextEncoder().encode("v1");
const signature = await crypto.subtle.sign(
  { name: "ML-DSA-65", context },
  privateKey,
  data,
);

Ключи ML-DSA можно импортировать и экспортировать в форматах "pkcs8", "spki", "jwk", "raw-public", "raw-private" и "raw-seed".

Подписи SLH-DSA

SLH-DSA (FIPS 205) — это не требующая состояния схема подписи на основе хеш-функций. Доступны все двенадцать наборов параметров, сочетающих семейство хеш-функций (SHA2 или SHAKE), уровень безопасности (128, 192 или 256) и компромисс между s (меньший размер подписи) и f (большая скорость):

  • SLH-DSA-SHA2-128s, SLH-DSA-SHA2-128f, SLH-DSA-SHA2-192s, SLH-DSA-SHA2-192f, SLH-DSA-SHA2-256s, SLH-DSA-SHA2-256f
  • SLH-DSA-SHAKE-128s, SLH-DSA-SHAKE-128f, SLH-DSA-SHAKE-192s, SLH-DSA-SHAKE-192f, SLH-DSA-SHAKE-256s, SLH-DSA-SHAKE-256f

В SLH-DSA используется тот же поток generateKey, sign и verify, что и в ML-DSA, включая необязательный context:

const { publicKey, privateKey } = await crypto.subtle.generateKey(
  { name: "SLH-DSA-SHAKE-128f" },
  true,
  ["sign", "verify"],
);

const data = new TextEncoder().encode("Hello, Deno!");
const signature = await crypto.subtle.sign(
  { name: "SLH-DSA-SHAKE-128f" },
  privateKey,
  data,
);

Ключи SLH-DSA можно импортировать и экспортировать в форматах "pkcs8", "spki", "jwk", "raw-public" и "raw-private".

Инкапсуляция ключей ML-KEM

ML-KEM (FIPS 203) — это механизм инкапсуляции ключей: одна сторона инкапсулирует новый общий секрет с помощью открытого ключа получателя, а получатель декапсулирует полученный шифротекст, чтобы восстановить тот же секрет. Доступны наборы параметров ML-KEM-512, ML-KEM-768 и ML-KEM-1024.

Получатель создаёт пару ключей и публикует открытый ключ (ключ инкапсуляции). Отправитель вызывает encapsulateKey, который возвращает шифротекст ciphertext для отправки получателю, а также sharedKey CryptoKey для алгоритма, указанного третьим аргументом. Получатель передаёт шифротекст в decapsulateKey, чтобы получить тот же ключ:

const { publicKey, privateKey } = await crypto.subtle.generateKey(
  { name: "ML-KEM-768" },
  true,
  ["encapsulateKey", "decapsulateKey"],
);

// Sender: encapsulate a shared AES-GCM key to the recipient's public key.
const { ciphertext, sharedKey } = await crypto.subtle.encapsulateKey(
  { name: "ML-KEM-768" },
  publicKey,
  { name: "AES-GCM", length: 256 },
  false,
  ["encrypt", "decrypt"],
);

// Recipient: decapsulate the ciphertext to recover the same key.
const recovered = await crypto.subtle.decapsulateKey(
  { name: "ML-KEM-768" },
  privateKey,
  ciphertext,
  { name: "AES-GCM", length: 256 },
  false,
  ["encrypt", "decrypt"],
);

encapsulateBits и decapsulateBits — это низкоуровневые варианты: они возвращают необработанный общий секрет в виде ArrayBuffer вместо его импорта как CryptoKey. Ключ декапсуляции (закрытый ключ) также предоставляет getPublicKey(), возвращающий соответствующий ему ключ инкапсуляции (открытый ключ).

createImageBitmap

Deno поддерживает createImageBitmap() для декодирования изображений в объекты ImageBitmap, которые можно использовать с OffscreenCanvas.

Поддерживаемые форматы входных данных

Формат Примечания
PNG
JPEG
BMP
GIF Добавлен в Deno 2.7
WebP Добавлен в Deno 2.7
const data = await Deno.readFile("./image.gif");
const bitmap = await createImageBitmap(new Blob([data]));
console.log(bitmap.width, bitmap.height);

Блокировка файлов

Deno.FsFile поддерживает рекомендательную блокировку файлов для координации доступа между процессами:

  • lock(exclusive?) — устанавливает блокировку. По умолчанию она общая (для чтения); передайте true, чтобы установить исключительную блокировку (для записи). Ожидание завершится, когда будет снята несовместимая блокировка.
  • lockSync(exclusive?) — синхронный вариант lock().
  • tryLock(exclusive?) — неблокирующий вызов. Возвращает true, если блокировка установлена, и false в противном случае. Добавлен в Deno 2.7.
  • tryLockSync(exclusive?) — синхронный вариант tryLock().
const file = await Deno.open("./data.txt", { read: true, write: true });

const locked = await file.tryLock(true); // exclusive
if (locked) {
  await file.write(new TextEncoder().encode("hello"));
  await file.unlock();
} else {
  console.log("File is locked by another process, skipping.");
}
file.close();

Отклонения других API от спецификации

API Cache

Реализованы только следующие API:

  • CacheStorage::open()
  • CacheStorage::has()
  • CacheStorage::delete()
  • CacheStorage::keys() (Deno 2.8+)
  • Cache::match()
  • Cache::put()
  • Cache::delete()
  • Cache::keys() (Deno 2.8+)

Некоторые отличия от браузеров:

  1. Нельзя передавать API относительные пути. В качестве запроса можно использовать экземпляр Request или URL либо строку URL.
  2. match() и delete() пока не поддерживают параметры запроса.

Последнее обновление: 25 июня 2026 г.

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/reference/web_platform_apis

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API