Deno 1.15 Release Notes
Deno 1.15 has been tagged and released with the following features and changes:
- New crypto APIs
- FFI improvements
deno uninstall
subcommanddeno lint --watch
- In memory CA certificates
- Nested testing API
- API stabilizations
- V8 9.5 update
- Improving Node Compatibility
If you already have Deno installed, you can upgrade to 1.15 by running
deno upgrade
If you are installing Deno for the first time, you can use one of the methods listed below:
# Using Shell (macOS and Linux):
curl -fsSL https://deno.land/x/install/install.sh | sh
# Using PowerShell (Windows):
iwr https://deno.land/x/install/install.ps1 -useb | iex
# Using Homebrew (macOS):
brew install deno
# Using Scoop (Windows):
scoop install deno
# Using Chocolatey (Windows):
choco install deno
New crypto APIs
In line with our goal to have a feature complete Web Crypto API by the end of the year, we have made good progress this release:
crypto.subtle.exportKey()
:- RSA keys can now be exported in spki format.
crypto.subtle.importKey()
:- ECDSA keys can now be imported in raw format.
crypto.subtle.deriveBits()
:- ECDH derivation is now supported (only for P256 keys).
crypto.subtle.wrapKey()
:- Key wrapping is now supported for all key & format combinations supported by
crypto.subtle.exportKey()
.
- Key wrapping is now supported for all key & format combinations supported by
crypto.subtle.encrypt()
:- AES-CBC encryption is now supported.
crypto.subtle.decrypt()
:- AES-CBC decryption is now supported.
You can subscribe to this tracking issue to be notified of further progress on the Web Crypto API.
Thanks to Divy Srivastava for the significant work on the Web Crypto implementation in Deno.
FFI improvements
FFI was added in Deno 1.13, this API allows users to call libraries written in languages that support C ABI such as C, C++, C#, Kotlin, Nim, Rust or Zig.
This release adds support for two very useful features to FFI API: non-blocking calls and buffer arguments.
Non-blocking calls
There are many use cases where users might want to run CPU-bound FFI functions in the background without blocking other tasks on the main thread.
With this release symbols can be marked nonblocking
in Deno.dlopen
. These
function calls will run on a dedicated blocking thread and will return a
Promise
resolving to the desired result
.
Example of executing expensive FFI calls with Deno:
// sleep.c
#ifdef _WIN32
#include <Windows.h>
#else
#include <time.h>
#endif
int sleep(unsigned int ms) {
#ifdef _WIN32
Sleep(ms);
#else
struct timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000;
nanosleep(&ts, NULL);
#endif
}
Calling it from Deno:
// nonblocking_ffi.ts
const library = Deno.dlopen("./sleep.so", {
sleep: {
parameters: ["usize"],
result: "void",
nonblocking: true,
},
});
library.symbols.sleep(500).then(() => console.log("After"));
console.log("Before");
Result:
$ deno run --allow-ffi --unstable nonblocking_ffi.ts
Before
After
Buffer arguments
Prior to 1.15 arguments to FFI symbols were limited to primitive types, but this release adds support for using buffers as arguments for FFI calls.
When calling FFI symbols with a buffer, the next argument must be buffer’s length.
Example:
// print_buffer.rs
#[no_mangle]
pub extern "C" fn print_buffer(ptr: *const u8, len: usize) {
let buf = unsafe { std::slice::from_raw_parts(ptr, len) };
println!("{:?}", buf);
}
Calling it from Deno:
// print_buffer.ts
const library = Deno.dlopen("./print_buffer.so", {
print_buffer: {
parameters: ["buffer", "usize"],
result: "void",
},
});
const buffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
dylib.symbols.print_buffer(buffer, buffer.length);
Result:
$ deno run --allow-ffi --unstable print_buffer.ts
[1, 2, 3, 4, 5, 6, 7, 8]
In addition to passing buffers-as-arg, we recognize the importance of being able to use buffers-as-return-value and plan to support this feature in the coming releases.
For more information on the FFI API visit manual page.
Thanks to Elias Sjögreen and Divy Srivastava for implementing these features.
deno uninstall
command
This release introduces a deno uninstall
subcommand. It lets you remove a
command previously installed with deno install
.
$ deno install
Check https://deno.land/std/examples/welcome.ts
✅ Successfully installed welcome
/Users/lucacasonato/.deno/bin/welcome
$ welcome
Welcome to Deno!
$ deno uninstall welcome
deleted /Users/lucacasonato/.deno/bin/welcome
✅ Successfully uninstalled welcome
Uninstalling a command was previously already possible by just removing the
command file from the .deno/bin
directory.
deno lint --watch
deno lint
now supports the --watch
flag that will keep the process alive
after printing diagnostics and watch for file changes to update diagnostics from
changed files.
As in other subcommands that support --watch
flag, the files that are needed
to be watched are automatically discovered by Deno.
Thanks to @CGQAQ
who contributed this feature.
In memory CA certificates
Over the past year, Deno has accumulated 3 different APIs that all deal with
TLS: Deno.connectTls
for establishing outbound TLS connections,
Deno.startTls
for upgrading existing connections to TLS, and
Deno.createHttpClient
for changing HTTP and TLS settings for outbound HTTP
requests.
All of these three APIs had various ways to specify custom CA certificates. This
has now been unified. All three APIs now take a caCerts
option. This property
must be given as an array of strings, where each string is a PEM encoded X.509
certificate. Multiple certificates can be specified in this array.
An example:
const caCert = await Deno.readTextFile("./custom_ca_cert.pem");
const client = Deno.connectTls({
hostname: "database.internal",
port: 4443,
caCerts: [caCert],
});
This release also removes the unstable caData
option from
Deno.createHttpClient
because this new API replaces it.
Nested testing API
This release adds a new experimental sub-steps API to the Deno testing
framework. This addition allows users to define sub-steps for tests defined by
Deno.test
. These sub steps get their own sanitizer scopes
and are rendered in the test runner with indents. The new API is general enough
so it can be wrapped by polyfills to emulate existing test frameworks like
mocha
or node-tap
. The original explainer for this new API
explains it in more detail.
Here is an example of a test that uses the new API. It creates a database connection, runs some queries against it in sub tests and then closes the connection.
Deno.test("database test", async (t) => {
const db = await Database.connect("postgres://localhost/test");
await t.step("insert user", async () => {
const users = await db.query(
"INSERT INTO users (name) VALUES ('Deno') RETURNING *",
);
assertEquals(users.length, 1);
assertEquals(users[0].name, "Deno");
});
await t.step("insert book", async () => {
const books = await db.query(
"INSERT INTO books (name) VALUES ('The Deno Manual') RETURNING *",
);
assertEquals(books.length, 1);
assertEquals(books[0].name, "The Deno Manual");
});
db.close();
});
The same test written in Mocha style would look like this:
describe("database test", () => {
let db: Database;
beforeAll(async () => {
db = await Database.connect("postgres://localhost/test");
});
it("insert user", async () => {
const users = await db!.query(
"INSERT INTO users (name) VALUES ('Deno') RETURNING *",
);
assertEquals(users.length, 1);
assertEquals(users[0].name, "Deno");
});
it("insert book", async () => {
const books = await db!.query(
"INSERT INTO books (name) VALUES ('The Deno Manual') RETURNING *",
);
assertEquals(books.length, 1);
assertEquals(books[0].name, "The Deno Manual");
});
afterAll(() => {
db!.close();
});
});
For those more familiar with this style, we have written a simple polyfill for Mocha that builds on top of this new API: https://gist.github.com/lucacasonato/54c03bb267074aaa9b32415dbfb25522.
Inline with this polyfill, we now have some examples showcasing how to use
chai
or sinon
for assertions in Deno tests:
- https://deno.land/[email protected]/testing/chai_example.ts
- https://deno.land/[email protected]/testing/sinon_example.ts
Please note that this API is still experimental and may change in the future. Feedback on this API is very welcome!
API stabilizations
1.15 brings stabilization of several Deno APIs:
Deno.kill
Deno.Process.kill
Deno.resolveDns
Using these APIs no longer requires passing --unstable
flag on the CLI.
We plan to stabilize the Deno.signal()
API in the upcoming release.
Stabilization of URLPattern
API in sync with Chromium
Last release introduced a new unstable web platform API for matching URLs
against patterns. URLPattern
is a builtin alternative to the popular
path-to-regexp
library.
The pattern syntax is very similar to
path-to-regexp
. What sets
URLPattern
apart is that it is capable of matching more than just paths - it
can match each part of a URL (protocol, hostname, pathname, query string, hash,
etc.) individually.
This release stabilizes this API in sync with Chromium. It will be available today in Deno 1.15, and on October 19th in the 95 release of Google Chrome and Microsoft Edge.
Documentation and examples are available on MDN: https://developer.mozilla.org/en-US/docs/Web/API/URLPattern.
V8 9.5 update
Deno 1.15 includes V8 9.5. This release introduces the new “Intl.DisplayNames
v2” JavaScript API, an extended timeZoneName option for Intl.DateTimeFormat
,
and support for the “WebAssembly Exception Handling (Wasm EH) proposal”.
Details about each change are available in the V8 9.5 release notes.
Improving Node Compatibility
To make it easier to run Node programs in Deno, a new flag --compat
was added
(this flag requires --unstable
). When this flag is present Deno will
automatically set up Node global variables (like process
) and provide all
built-in modules available in Node. This means Deno can now handle code like
this:
import { readFileSync } from "fs";
let passwd = readFileSync("/etc/passwd", "utf-8");
console.log(passwd);
console.log(process.pid);
This release is just the first pass for --compat
. We will be putting a lot of
work into improving compat mode in coming releases, working towards Node
emulation.
std/node
is a module that provides a
compatibility layer for Node APIs, making it possible to run a subset of Node
programs in Deno. The release of std 0.111.0 brings a big update to this
compatibility layer, including addition of some highly desired modules (dns
,
http
and net
), as well as many updates to the crypto
module.