Today we are releasing Deno 1.8.0. This release contains a massive amount of new
features and stabilizations:

If you already have Deno installed you can upgrade to 1.8 by running
deno upgrade. If you are installing Deno for the first time, you can use one
of the methods listed below:

curl -fsSL | sh

iwr -useb | iex

brew install deno

scoop install deno

choco install deno

Experimental support for the WebGPU API

The WebGPU API gives developers a low level, high performance, cross
architecture way to program GPU hardware from JavaScript. It is the effective
successor to WebGL on the Web. The spec has not yet been finalized, but support
is currently being added to Firefox, Chromium, and Safari; and now also in Deno.

This API gives you access to GPU rendering and general purpose GPU compute right
from within Deno. Once finished, stabilized, and unflagged, this will provide a
portable way to access GPU resources from web, server, and developer machine.

GPUs allow programmers to make some numerical algorithms highly parallel. This
is useful beyond rendering graphics and games. Effective use of GPUs in Machine
Learning has enabled more complex neural networks – what is called Deep
Learning. The rapid progress in computer vision, translation, image generation,
re-enforcement learning, and more all stem from making effective use of GPU

These days, most neural networks are defined in Python with the computation
offloaded to GPUs. We believe JavaScript, instead of Python, could act as an
ideal language for expressing mathematical ideas if the proper infrastructure
existed. Providing WebGPU support out-of-the-box in Deno is a step in this
direction. Our goal is to run Tensorflow.js on
Deno, with GPU acceleration. We expect this to be achieved in the coming weeks
or months.

Here is a basic example that demonstrates accessing an attached GPU device, and
reading out the name and supported features:

const adapter = await navigator.gpu.requestAdapter();

if (adapter) {

console.log(`Found adapter: ${}`);

const features = [...adapter.features.values()];

console.log(`Supported features: ${features.join(", ")}`);

} else {

console.error("No adapter found");


Here is a little example that demonstrates the GPU rendering a simple red
triangle on a green background using a render shader:

$ deno run --unstable --allow-write=output.png

A Simple Red Triangle On A Green Background

Note the use of WebAssembly to write the PNG.
For more examples visit this repository:

The final PR weighed in at a whopping 15.5k lines of code, and took a whole 5
months to merge after opening. Many thanks to
crowlKats who led the integration of WebGPU into
Deno. We would also like to thank to all contributors to the
wgpu and gfx-rs projects that underpin the
WebGPU implementation in Deno. Special thanks also to
kvark, editor on the WebGPU spec, and the lead
developer of wgpu and gfx-rs, for the great guidance while implementing the

ICU support

ICU support has been the second most requested feature in Deno repository. We’re
happy to announce that Deno v1.8 ships with full ICU support.

All JavaScript APIs depending on ICU should now match browser APIs.

Try it in the REPL:

$ deno

Deno 1.8.0

exit using ctrl+d or close()

> const d = new Date(Date.UTC(2020, 5, 26, 7, 0, 0));


> d.toLocaleString("de-DE", {

weekday: "long",

year: "numeric",

month: "long",

day: "numeric",


"Freitag, 26. Juni 2020"

Revamped coverage tooling: deno coverage

This release expands our coverage infrastructure to add some great new
capabilities. The main change in this release is that coverage handling is now
split into coverage collection and coverage reporting.

Previously coverage collection and reporting would all happen in a single
subcommand, by specifying the --coverage flag when starting deno test. Now
the --coverage flag for deno test takes an argument – a path to a directory
where to store the collected profiles. This is the coverage collection. In a
second step you now call deno coverage with the path to the directory storing
the coverage profiles. This subcommand can either return a report as pretty text
output right on the console, or it can output an
lcov file (--lcov
flag) for use with tools like genhtml,, or

We have been dogfooding this feature on
deno_std for a few days now. We upload
a coverage report to for each commit. You can view these here Adding this was trivial, with only a 10
line change to our GitHub Actions workflow:

- name: Run tests

- run: deno test --unstable --allow-all

+ run: deno test --coverage=./cov --unstable --allow-all


+ - name: Generate lcov

+ run: deno coverage --unstable --lcov ./cov > cov.lcov


+ - name: Upload coverage

+ uses: codecov/codecov-action@v1

+ with:

+ name: ${{ matrix.os }}-${{ matrix.deno }}

+ files: cov.lcov

For an example of integration with, see this repository:

Import maps are now stable

Import maps were stabilized in Chrome 89,
and following that our implementation has been updated to match the latest
revision of the specification and is now also considered stable. This means that
the --unstable flag is no longer required when using --import-map.

$ deno run --import-map=./import_map.json ./mod.ts

Additionally the --import-map flag now accepts not only local paths, but also
URLs, allowing you to load import maps from remote servers.

$ deno run --import-map= ./mod.ts

Import maps allow a user to use so-called “bare” specifiers for dependencies,
instead of relative or absolute file / http URLs:

import * as http from "std/http";


"imports": {

"std/http": ""



Users should keep in mind that import maps are not composable: this means
you can only provide a single import map to deno run / deno test. Because of
this library authors should still use regular, non-bare specifiers (relative or
absolute file / http URLs); otherwise the users of the library will manually
need to add your libraries (and your libraries dependencies) bare specifiers
into their import map.

A much more useful feature for import maps is ability to remap regular
specifiers to completely different ones. For example if you have some broken
dependency that is deeply nested in your module graph you can replace it with
fixed version before it’s fixed upstream, or if you use a build process that
adds hashes to your modules filenames, you can refer to the file without hashes
in your source code and remap the specifiers only at runtime using an import

For more examples and a detailed explanation refer
to the specification.

Auth token support for fetching modules

Not all code is openly available on the public internet. Previously Deno had no
capability to download code from a server that required authentication. In this
release we have added the ability for users to specify per domain auth tokens
that are used when fetching modules for the first time.

To do this the Deno CLI will look for an environment variable named
DENO_AUTH_TOKENS to determine what authentication tokens it should consider
using when requesting remote modules. The value of the environment variable is
in the format of a n number of tokens delimited by a semi-colon (;) where each
token is in the format of {token}@{hostname[:port]}.

For example a single token for would look something like this:

And multiple tokens would look like this:;

When Deno goes to fetch a remote module, where the hostname matches the hostname
of the remote module, Deno will set the Authorization header of the request to
the value of Bearer {token}. This allows the remote server to recognize that
the request is an authorized request tied to a specific authenticated user, and
provide access to the appropriate resources and modules on the server.

For a more detailed usage guide and instructions for configuring your
environment to pull from private GitHub repos,
see the related manual entry.

Exit sanitizer for Deno.test

The Deno.test API already has
two sanitizers
that help ensure that your code is not “leaking” ops or resources – ie. that all
open file/network handles are closed before test case ends, and that there are
no more pending syscalls.

Deno 1.8 adds a new sanitizer that ensures that tested code doesn’t call
Deno.exit(). Rogue exit statements can signal false positive test results and
are most often misused or were forgotten to be removed.

This sanitizer is enabled by default for all tests, but can be disabled by
setting the sanitizeExit boolean to false in the test definition.


name: "false success",

fn() {



sanitizeExit: false,



name: "failing test",

fn() {

throw new Error("this test fails");



You can run this script yourself:
deno test

Deno.permissions APIs are now stable

Deno’s security model is based on permissions. Currently these permissions can
only be granted when the application is started. This works well for most
scenarios, but in some cases it is a better user experience to request / revoke
permissions at runtime.

In Deno 1.8 there is now a stable API to query, request, and revoke
permissions. These APIs are contained in the Deno.permissions object. Here is
an example of how this works:

function homedir() {

try {

console.log(`Your home dir is: ${Deno.env.get("HOME")}`);

} catch (err) {

console.log(`Failed to get the home directory: ${err}`);




const { granted } = await Deno.permissions.request({ name: "env" });

if (granted) {

console.log(`You have granted the "env" permission.`);

} else {

console.log(`You have not granted the "env" permission.`);



await Deno.permissions.revoke({ name: "env" });


You can run this script yourself:
deno run and Deno.symlink APIs have been stabilized

This release brings stabilization four APIs related to symlinks:

  • Deno.linkSync
  • Deno.symlink
  • Deno.symlinkSync

Before stabilization these APIs went through a security review and proper
permissions are required to use them. and Deno.linkSync require both read and write permissions for both
source and target paths.

Deno.symlink and Deno.symlinkSync require write permissions for target path.

More granular Deno.metrics

As Deno becomes more stable it is becoming more important have easy ways for
developers to instrument their applications. This starts at the lowest level, at
the runtime itself. In Deno all privileged operations in JS (the ones that go to
Rust), are done via a single central interface between JS and Rust. We call the
requests going over that interface “ops”. For example, calling would
invoke the op_open_async op to the privileged side, which would return the
resource id of the opened file (or an error).

More than two years ago, on Oct 11, 2018 we added a way for you to view metrics
for all of the ops between Rust and JS: Deno.metrics. This API currently
exposes the count of started, and completed synchronous and asynchronous ops,
and the amount of data that has been sent over the ops interface. So far this
has been limited to combined data for all of the different ops. There was no way
to figure out which ops were invoked how many times, only all ops in general.

When running with --unstable, this release adds a new field to Deno.metrics
called ops. This field contains per op information about how often the API was
invoked and how much data has been transmitted over it. This allows for far more
granular instrumentation of the runtime.

Here is an example of this working:

$ deno --unstable

Deno 1.8.0

exit using ctrl+d or close()

> Deno.metrics().ops["op_open_async"]


> await"./")

File {}

> Deno.metrics().ops["op_open_async"]


opsDispatched: 1,

opsDispatchedSync: 0,

opsDispatchedAsync: 1,

opsDispatchedAsyncUnref: 0,

opsCompleted: 1,

opsCompletedSync: 0,

opsCompletedAsync: 1,

opsCompletedAsyncUnref: 0,

bytesSentControl: 54,

bytesSentData: 0,

bytesReceived: 22


In an upcoming release this new information will be used by the async op
sanitizer in Deno.test to give more actionable errors when an async op is not
completed before test completion. We have already seen this feature being used
to instrument applications and pipe the data into monitoring software:

Screenshot Of A Website With A Table Displaying The Output Of Deno.metrics

JSON support for deno fmt

deno fmt can now format .json and .jsonc files. Just like with JS/TS, the
formatter will also format json and jsonc codeblocks inside of markdown files.

IIFE bundle support for Deno.emit

The built-in bundler can now emit bundles in Immediately Invoked Function
Expression (IIFE) format.

By default output format will still be esm, but users can change this by
setting the EmitOptions.bundle option to iife:

const { files } = await Deno.emit("/a.ts", {

bundle: "iife",

sources: {

"/a.ts": `import { b } from "./b.ts";


"/b.ts": `export const b = "b";`,




Results in:

(function() {

const b = "b";


return {



You can run this script yourself:
deno run --unstable

This is particularly useful for creating bundles for older browsers that do not
support ESM.

deno lsp is now stable

We have been working on a replacement for our old editor integration for VS
Code, the Deno extension for the last few months. The old extension only worked
for VS Code, and the resolved types did not always match the ones in the Deno

In Deno 1.6 we released deno lsp in canary – a builtin language server for
Deno. LSP allows us to provide editor integration to all LSP capable editors
from just a single codebase. The built in language server is built on the same
architecture as the rest of the Deno CLI – it thus provides TypeScript
diagnostics the same way as the rest of the CLI.

Two weeks ago, in Deno 1.7.5 we stabilized deno lsp and switched our
offical VS Code extension
to use it. So far we have gotten some great feedback, and will be working to
address all reported issues. If you are running into issues with the extension,
please report it on our issue tracker. We can not fix issues that we do not know

In addition to the offical VS Code integration, more community integrations have
been created that are built on deno lsp:

TypeScript 4.2

Deno 1.8 ships with the latest stable version of TypeScript.

For more information on new features in Typescript 4.2 see
Announcing TypeScript 4.2


Please enter your comment!
Please enter your name here