From async-await to ArrayBuffers, the JavaScript language has changes significantly in the decade since Node.js was designed. Deno takes advantage of these developments and incorporate lessons learned in the development of Node to provide a new JavaScript platform built on V8 and Rust. This talk will teach the audience how to get started with Deno.
Report
Share
Report
Share
1 of 37
More Related Content
JS Fest 2019. Ryan Dahl. Deno, a new way to JavaScript
2. Disclaimer
This talk is aimed at experienced enthusiasts
If this isn't you: Don't Panic
Ignore this talk - use Node. Node isn't going anywhere!
3. Deno is a new command-line runtime
for executing JavaScript and TypeScript
Primarily it is built on top of:
● V8
● Rust
● Tokio (event loop)
● TypeScript
4. But why!? Isn't this exactly what Node does?
JavaScript (both the language itself and the ecosystem around it) has changed
significantly since Node was designed in 2009. Notably:
● Promises / Async / Await
● ES Modules
● Typed Arrays
Node has problems:
● A poorly designed module system, with centralized distribution.
● Lots of legacy APIs that must be supported.
● Security.
(These problems aren't unique to Node. Python and Ruby suffer similarly)
5. I want a fun and productive system for scripting.
A good scripting platform is too useful of a tool to
shrug and accept the status quo.
I find neither Node nor
Python nor Ruby nor any
other dynamic language
platform satisfactory.
6. Deno attempts to correct design mistakes in Node by
radically breaking compatibility
● ES modules are the one and only module system
○ HTTP URLs are used to link to third party code
○ Deno has the ability to fetch resources itself, so it is its own package manager.
● Deno is secure by default
○ Users must give extra permission to access the disk, network, or otherwise do privileged
operations.
● Deno maintains browser compatibility
○ The subset of Deno programs which are written completely in JavaScript and do not use the
global Deno object should also run in a modern web browser without change.
11. Deno is (kind of) like an OS
Linux
Processes
Syscalls
File descriptors (fd)
Scheduler
Userland: libc++ / glib / boost
/proc/$$/stat
man pages
Deno
Web Workers
Ops
Resource ids (rid)
Tokio
deno_std
deno.metrics()
deno --types
13. V8 (C++)
libdeno (C++)
deno process (Rust)
deno_recv_cb
deno_send
deno::Isolate (Rust)
Tokio thread pool (Rust)
deno_buf
"ops"
Resources (Rust)
stdio
TCP socket
child process
... etc
Internal Design (Very Simplified)
thread1 thread2 thread3 thread4
Deno.core.send()
Deno.core.recv()
//js (JS)
14. Embedding Deno
https://crates.io/crates/deno
Deno is released as a standalone executable, but it's also embeddable.
There are many situations where one might want to execute a bit of JavaScript,
but shelling out to Node (or Deno) is too insecure, complex, or generally
inappropriate:
○ Databases often use a JavaScript for Map Reduce functions
○ Serverless products like Lambda@Edge or Cloudflare Workers
Using raw V8 is difficult
16. deno_std (Standard Modules)
Deno core is kept as minimal as possible.
However it's useful to have high quality standard modules.
https://github.com/denoland/deno_std
● This partially addresses the "dependency hell" problem by not having external
deps.
● All code is reviewed by me (at least superficially)
● Is tagged with each Deno release: https://deno.land/std@v0.3.2/
17. Deno Performance
We continuously run benchmarks, to ensure our performance goes in the right
direction over time. Startup time is shown below (3x faster than Node)
25. ES Modules map bijectively onto JavaScript files
This is a wonderful simplification over languages where "modules" and "source
code files" are not the same. It is one less concept for users to grok.
Files map bijectively onto URLs. Therefore modules map to URLs.
ES Module <=> JS File <=> JS URL
This is a very simple and file-centric programming model.
26. URL <=> source code <=> Module
For this reason, we've chosen to deviate from the convention of importing
TypeScript files without file extensions.
We require that module specifies that are paths to actual files:
import { red } from "https://deno.land/std/colors/mod.ts";
This maintains the bijection, and if it sticks, it will provide a simpler conceptual
basis for new users.
Please consider adopting this convention for TS code outside of Deno.
27. UNIX is also a very file-centric programming model
but over data rather than source files.
Inspired by this, Deno has the following design constraint:
1. Users should be able to allocate a Typed Array in JS, and tell the kernel to
read(2) into it.
2. Users should be able to pass a locally allocated Typed Array to the kernel for
a write(2) syscall without an internal memcpy happening.
Colloquially this is known as "zero-copy"
28. UNIX inspired I/O
Traditional UNIX programs use blocking reads and writes to process data:
char buf[64];
size_t n;
for (;;) {
n = read(STDIN_FILENO, buf, 64);
if (n <= 0) break;
n = write(STDOUT_FILENO, buf, n);
if (n <= 0) break;
}
29. UNIX inspired I/O
Traditional UNIX programs use blocking reads and writes to process data:
char buf[64];
size_t n;
for (;;) {
n = read(STDIN_FILENO, buf, 64);
if (n <= 0) break;
n = write(STDOUT_FILENO, buf, n);
if (n <= 0) break;
}
Zero-copy.
Fixed buf allocation.
Thus: efficient
30. UNIX inspired I/O
Traditional UNIX programs use blocking reads and writes to process data:
char buf[64];
size_t n;
for (;;) {
n = read(STDIN_FILENO, buf, 64);
if (n <= 0) break;
n = write(STDOUT_FILENO, buf, n);
if (n <= 0) break;
}
Different data streams
abstracted as a FD
Thus: composable
Zero-copy.
Fixed buf allocation.
Thus: efficient
31. UNIX inspired I/O
Traditional UNIX programs use blocking reads and writes to process data:
char buf[64];
size_t n;
for (;;) {
n = read(STDIN_FILENO, buf, 64);
if (n <= 0) break;
n = write(STDOUT_FILENO, buf, n);
if (n <= 0) break;
}
Different data streams
abstracted as a FD
Thus: composable
Does not read more
than it can handle.
Thus: back-pressure
Zero-copy.
Fixed buf allocation.
Thus: efficient
32. Go's Reader/Writer is the modern ideal of UNIX
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
The interfaces model the
read(2) write(2)
syscalls without relying on
FDs (which imply
expensive syscalls).
Not every type of data
stream needs a FD
E.G. gzip.
37. Building a runtime around Reader/Writer allows us
to port other concepts, tests, and documentation
from Go.
Good ideas should be reused - and there are many of them in Go.
Examples:
Buffer ported from bytes.Buffer
copy() ported from io.Copy()
BufReader() ported from bufio.Reader