summaryrefslogtreecommitdiff
path: root/website/manual.md
diff options
context:
space:
mode:
Diffstat (limited to 'website/manual.md')
-rw-r--r--website/manual.md656
1 files changed, 656 insertions, 0 deletions
diff --git a/website/manual.md b/website/manual.md
new file mode 100644
index 000000000..bf5f6d237
--- /dev/null
+++ b/website/manual.md
@@ -0,0 +1,656 @@
+# Deno Manual
+
+[toc]
+
+## Disclaimer
+
+A word of caution: Deno is very much under development. We encourage brave early
+adopters, but expect bugs large and small. The API is subject to change without
+notice.
+
+[Bug reports](https://github.com/denoland/deno/issues) do help!
+
+## Introduction
+
+### Philosophy
+
+Deno aims to be a useful multitool tool for the modern programmer.
+
+It will always be distributed as a single executable - and that executable will
+be sufficient software to run any deno program. Given a URL to a deno program,
+you should be able to execute it with nothing more than <a
+href="https://deno.land/benchmarks.html#size">the 50M deno executable</a>.
+
+Deno explicitly takes on the role of both runtime and package manager. It uses a
+standard browser-compatible protocol for loading modules: URLs.
+
+Deno provides security guarantees about how programs can access your system with
+the default being the most restrictive secure sandbox.
+
+Deno provides <a href="https://github.com/denoland/deno_std">a set of reviewed
+(audited) standard modules</a> that are guaranteed to work with Deno.
+
+Deno is opinionated and defines <a
+href="https://github.com/denoland/deno_std#style-guide">style guides</a> and has
+<a href="https://github.com/denoland/deno_std/tree/master/prettier">automated
+formatters</a>.
+
+### Design goals
+
+- Support TypeScript out of the box.
+
+- No `package.json`. No npm. Not explicitly compatible with Node.
+
+- Like the browser, allows imports from URLs:
+
+ ```typescript
+ import * as log from "https://deno.land/x/std/log/mod.ts";
+ ```
+
+- Remote code is fetched and cached on first execution, and never updated until
+ the code is run with the `--reload` flag. (So, this will still work on an
+ airplane. See `~/.deno/src` for details on the cache.)
+
+- Uses "ES Modules" and does not support `require()`.
+
+- File system and network access can be controlled in order to run sandboxed
+ code. Access between V8 (unprivileged) and Rust (privileged) is only done via
+ serialized messages defined in this
+ [flatbuffer](https://github.com/denoland/deno/blob/master/src/msg.fbs). This
+ makes it easy to audit. For example, to enable write access use the flag
+ `--allow-write` or for network access `--allow-net`.
+
+- Only ship a single executable.
+
+- Always dies on uncaught errors.
+
+- [Aims to support top-level `await`.](https://github.com/denoland/deno/issues/471)
+
+### Browser compatibility
+
+The subset of Deno programs which are written completely in JavaScript and do
+not import the special `"deno"` module, ought to also be able to be run in a
+modern web browser without change.
+
+## Setup
+
+### Binary Install
+
+Deno works on OSX, Linux, and Windows. Deno is a single binary executable. It
+has no external dependencies.
+
+[deno_install](https://github.com/denoland/deno_install) provides convenience
+scripts to download and install the binary.
+
+Using Shell:
+
+```
+curl -fL https://deno.land/x/install/install.sh | sh
+```
+
+Or using PowerShell:
+
+```powershell
+iex (iwr https://deno.land/x/install/install.ps1)
+```
+
+_Note: Depending on your security settings, you may have to run
+`Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` first to allow downloaded
+scripts to be executed._
+
+With [Scoop](https://scoop.sh/):
+
+```
+scoop install deno
+```
+
+Deno can also be installed manually, by downloading a tarball or zip file at
+[github.com/denoland/deno/releases](https://github.com/denoland/deno/releases).
+These packages contain just a single executable file. You will have to set the
+executable bit on Mac and Linux.
+
+Once it's installed and in your \$PATH, try it:
+
+```
+deno https://deno.land/welcome.js
+```
+
+### Build from source
+
+```
+# Fetch deps.
+git clone --recurse-submodules https://github.com/denoland/deno.git
+cd deno
+./tools/setup.py
+
+# You may need to ensure that sccache is running.
+# (TODO it's unclear if this is necessary or not.)
+# prebuilt/mac/sccache --start-server
+
+# Build.
+./tools/build.py
+
+# Run.
+./target/debug/deno tests/002_hello.ts
+
+# Test.
+./tools/test.py
+
+# Format code.
+# TODO: set PYTHONPATH in format.ts when run API has env option.
+PYTHONPATH=third_party/python_packages deno ./tools/format.ts --allow-read --allow-run
+```
+
+#### Prerequisites
+
+To ensure reproducible builds, deno has most of its dependencies in a git
+submodule. However, you need to install separately:
+
+1. [Rust](https://www.rust-lang.org/en-US/install.html) >= 1.31.1
+2. [Node](https://nodejs.org/)
+3. Python 2.
+ [Not 3](https://github.com/denoland/deno/issues/464#issuecomment-411795578).
+
+Extra steps for Mac users:
+
+1. [XCode](https://developer.apple.com/xcode/)
+2. Openssl 1.1: `brew install openssl@1.1` (TODO: shouldn't be necessary)
+
+Extra steps for Windows users:
+
+1. Add `python.exe` to `PATH` (e.g. `set PATH=%PATH%;C:\Python27\python.exe`)
+2. Get [VS Community 2017](https://www.visualstudio.com/downloads/) with
+ `Desktop development with C++` toolkit and make sure to select the following
+ required tools listed below along with all C++ tools.
+ - Windows 10 SDK >= 10.0.17134
+ - Visual C++ ATL for x86 and x64
+ - Visual C++ MFC for x86 and x64
+ - C++ profiling tools
+3. Enable `Debugging Tools for Windows`. Go to `Control Panel` → `Programs` →
+ `Programs and Features` → Select
+ `Windows Software Development Kit - Windows 10` → `Change` → `Change` → Check
+ `Debugging Tools For Windows` → `Change` -> `Finish`.
+
+#### Other useful commands
+
+```
+# Call ninja manually.
+./third_party/depot_tools/ninja -C target/debug
+
+# Build a release binary.
+DENO_BUILD_MODE=release ./tools/build.py :deno
+
+# List executable targets.
+./third_party/depot_tools/gn ls target/debug //:* --as=output --type=executable
+
+# List build configuration.
+./third_party/depot_tools/gn args target/debug/ --list
+
+# Edit build configuration.
+./third_party/depot_tools/gn args target/debug/
+
+# Describe a target.
+./third_party/depot_tools/gn desc target/debug/ :deno
+./third_party/depot_tools/gn help
+
+# Update third_party modules
+git submodule update
+```
+
+Environment variables: `DENO_BUILD_MODE`, `DENO_BUILD_PATH`, `DENO_BUILD_ARGS`,
+`DENO_DIR`.
+
+## API reference
+
+### deno --types
+
+To get an exact reference of deno's runtime API, run the following in the
+command line:
+
+```
+deno --types
+```
+
+[This is what the output looks like.](https://gist.github.com/ry/46da4724168cdefa763e13207d27ede5)
+
+### Reference websites
+
+[TypeScript Deno API](https://deno.land/typedoc/index.html).
+
+If you are embedding deno in a Rust program, see
+[Rust Deno API](https://deno.land/rustdoc/deno/index.html).
+
+## Examples
+
+### An implementation of the unix "cat" program
+
+In this program each command-line argument is assumed to be a filename, the file
+is opened, and printed to stdout.
+
+```ts
+import * as deno from "deno";
+
+(async () => {
+ for (let i = 1; i < deno.args.length; i++) {
+ let filename = deno.args[i];
+ let file = await deno.open(filename);
+ await deno.copy(deno.stdout, file);
+ file.close();
+ }
+})();
+```
+
+The `copy()` function here actually makes no more than the necessary kernel ->
+userspace -> kernel copies. That is, the same memory from which data is read
+from the file, is written to stdout. This illustrates a general design goal for
+I/O streams in Deno.
+
+Try the program:
+
+```
+> deno https://deno.land/x/examples/cat.ts /etc/passwd
+```
+
+### TCP echo server
+
+This is an example of a simple server which accepts connections on port 8080,
+and returns to the client anything it sends.
+
+```ts
+import { listen, copy } from "deno";
+
+(async () => {
+ const addr = "0.0.0.0:8080";
+ const listener = listen("tcp", addr);
+ console.log("listening on", addr);
+ while (true) {
+ const conn = await listener.accept();
+ copy(conn, conn);
+ }
+})();
+```
+
+When this program is started, the user is prompted for permission to listen on
+the network:
+
+```
+> deno https://deno.land/x/examples/echo_server.ts
+⚠️ Deno requests network access to "listen". Grant? [yN] y
+listening on 0.0.0.0:8080
+```
+
+For security reasons, deno does not allow programs to access the network without
+explicit permission. To avoid the console prompt, use a command-line flag:
+
+```
+> deno https://deno.land/x/examples/echo_server.ts --allow-net
+```
+
+To test it, try sending a HTTP request to it by using curl. The request gets
+written directly back to the client.
+
+```
+> curl http://localhost:8080/
+GET / HTTP/1.1
+Host: localhost:8080
+User-Agent: curl/7.54.0
+Accept: */*
+```
+
+It's worth noting that like the `cat.ts` example, the `copy()` function here
+also does not make unnecessary memory copies. It receives a packet from the
+kernel and sends back, without further complexity.
+
+### File server
+
+This one serves a local directory in HTTP.
+
+```
+alias file_server="deno --allow-net --allow-read \
+ https://deno.land/x/http/file_server.ts"
+```
+
+Run it:
+
+```
+% file_server .
+Downloading https://deno.land/x/http/file_server.ts...
+[...]
+HTTP server listening on http://0.0.0.0:4500/
+```
+
+And if you ever want to upgrade to the latest published version:
+
+```
+file_server --reload
+```
+
+### Linking to third party code
+
+In the above examples, we saw that Deno could execute scripts from URLs. Like
+browser JavaScript, Deno can import libraries directly from URLs. This example
+uses a URL to import a test runner library:
+
+```ts
+import { test, assertEqual } from "https://deno.land/x/testing/mod.ts";
+
+test(function t1() {
+ assertEqual("hello", "hello");
+});
+
+test(function t2() {
+ assertEqual("world", "world");
+});
+```
+
+Try running this:
+
+```
+> deno https://deno.land/x/examples/example_test.ts
+Compiling /Users/rld/src/deno_examples/example_test.ts
+Downloading https://deno.land/x/testing/mod.ts
+Compiling https://deno.land/x/testing/mod.ts
+running 2 tests
+test t1
+... ok
+test t2
+... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+```
+
+Note that we did not have to provide the `--allow-net` flag for this program,
+and yet it accessed the network. The runtime has special access to download
+imports and cache them to disk.
+
+Deno caches remote imports in a special directory specified by the `$DENO_DIR`
+environmental variable. It default to `$HOME/.deno` if `$DENO_DIR` is not
+specified. The next time you run the program, no downloads will be made. If the
+program hasn't changed, it won't be recompiled either.
+
+**But what if `https://deno.land/` goes down?** Relying on external servers is
+convenient for development but brittle in production. Production software should
+always bundle its dependencies. In Deno this is done by checking the `$DENO_DIR`
+into your source control system, and specifying that path as the `$DENO_DIR`
+environmental variable at runtime.
+
+**How do you import to a specific version?** Simply specify the version in the
+URL. For example, this URL fully specifies the code being run:
+`https://unpkg.com/liltest@0.0.5/dist/liltest.js`. Combined with the
+aforementioned technique of setting `$DENO_DIR` in production to stored code,
+one can fully specify the exact code being run, and execute the code without
+network access.
+
+**It seems unwieldy to import URLs everywhere. What if one of the URLs links to
+a subtly different version of a library? Isn't it error prone to maintain URLs
+everywhere in a large project?** The solution is to import and re-export your
+external libraries in a central `package.ts` file (which serves the same purpose
+as Node's `package.json` file). For example, let's say you were using the above
+testing library across a large project. Rather than importing
+`"https://deno.land/x/testing/mod.ts"` everywhere, you could create a
+`package.ts` file the exports the third-party code:
+
+```ts
+export { test, assertEqual } from "https://deno.land/x/testing/mod.ts";
+```
+
+And throughout project one can import from the `package.ts` and avoid having
+many references to the same URL:
+
+```ts
+import { test, assertEqual } from "./package.ts";
+```
+
+This design circumvents a plethora of complexity spawned by package management
+software, centralized code repositories, and superfluous file formats.
+
+## Command line interface
+
+### Flags
+
+```
+> deno -h
+Usage: deno script.ts
+
+Options:
+ --allow-read Allow file system read access.
+ --allow-write Allow file system write access.
+ --allow-net Allow network access.
+ --allow-env Allow environment access.
+ --allow-run Allow running subprocesses.
+ -A, --allow-all Allow all permissions.
+ --recompile Force recompilation of TypeScript code.
+ -h, --help Print this message.
+ -D, --log-debug Log debug output.
+ -v, --version Print the version.
+ -r, --reload Reload cached remote resources.
+ --v8-options Print V8 command line options.
+ --types Print runtime TypeScript declarations.
+ --prefetch Prefetch the dependencies.
+ --info Show source file related info
+ --fmt Format code.
+
+Environment variables:
+ DENO_DIR Set deno's base directory.
+```
+
+### Environmental variables
+
+There are several env vars that control how Deno behaves:
+
+`DENO_DIR` defaults to `$HOME/.deno` but can be set to any path to control where
+generated and cached source code is written and read to.
+
+`NO_COLOR` will turn off color output if set. See https://no-color.org/. User
+code can test if `NO_COLOR` was set without having `--allow-env` by using the
+boolean constant `deno.noColor`.
+
+### V8 flags
+
+V8 has many many internal command-line flags, that you can see with
+`--v8-options`.
+[It looks like this.](https://gist.github.com/ry/1c5b080dcbdc6367e5612392049c9ee7)
+
+Particularly useful ones:
+
+```
+--async-stack-trace
+```
+
+## Internal details
+
+### Schematic diagram
+
+<img src="schematic_v0.2.png">
+
+### Profiling
+
+To start profiling,
+
+```sh
+# Make sure we're only building release.
+export DENO_BUILD_MODE=release
+# Build deno and V8's d8.
+./tools/build.py d8 deno
+# Start the program we want to benchmark with --prof
+./target/release/deno tests/http_bench.ts --allow-net --prof &
+# Exercise it.
+third_party/wrk/linux/wrk http://localhost:4500/
+kill `pgrep deno`
+```
+
+V8 will write a file in the current directory that looks like this:
+`isolate-0x7fad98242400-v8.log`. To examine this file:
+
+```sh
+D8_PATH=target/release/ ./third_party/v8/tools/linux-tick-processor
+isolate-0x7fad98242400-v8.log > prof.log
+# on macOS, use ./third_party/v8/tools/mac-tick-processor instead
+```
+
+`prof.log` will contain information about tick distribution of different calls.
+
+To view the log with Web UI, generate JSON file of the log:
+
+```sh
+D8_PATH=target/release/ ./third_party/v8/tools/linux-tick-processor
+isolate-0x7fad98242400-v8.log --preprocess > prof.json
+```
+
+Open `third_party/v8/tools/profview/index.html` in your brower, and select
+`prof.json` to view the distribution graphically.
+
+To learn more about `d8` and profiling, check out the following links:
+
+- [https://v8.dev/docs/d8](https://v8.dev/docs/d8)
+- [https://v8.dev/docs/profile](https://v8.dev/docs/profile)
+
+### Debugging with LLDB
+
+We can use LLDB to debug deno.
+
+```sh
+lldb -- target/debug/deno tests/worker.js
+> run
+> bt
+> up
+> up
+> l
+```
+
+To debug Rust code, we can use `rust-lldb`. It should come with `rustc` and is a
+wrapper around LLDB.
+
+```sh
+rust-lldb -- ./target/debug/deno tests/http_bench.ts --allow-net
+# On macOS, you might get warnings like
+# `ImportError: cannot import name _remove_dead_weakref`
+# In that case, use system python by setting PATH, e.g.
+# PATH=/System/Library/Frameworks/Python.framework/Versions/2.7/bin:$PATH
+(lldb) command script import "/Users/kevinqian/.rustup/toolchains/1.30.0-x86_64-apple-darwin/lib/rustlib/etc/lldb_rust_formatters.py"
+(lldb) type summary add --no-value --python-function lldb_rust_formatters.print_val -x ".*" --category Rust
+(lldb) type category enable Rust
+(lldb) target create "../deno/target/debug/deno"
+Current executable set to '../deno/target/debug/deno' (x86_64).
+(lldb) settings set -- target.run-args "tests/http_bench.ts" "--allow-net"
+(lldb) b op_start
+(lldb) r
+```
+
+### libdeno
+
+deno's privileged side will primarily be programmed in Rust. However there will
+be a small C API that wraps V8 to 1) define the low-level message passing
+semantics, 2) provide a low-level test target, 3) provide an ANSI C API binding
+interface for Rust. V8 plus this C API is called "libdeno" and the important
+bits of the API is specified here:
+[deno.h](https://github.com/denoland/deno/blob/master/libdeno/deno.h)
+[libdeno.ts](https://github.com/denoland/deno/blob/master/js/libdeno.ts)
+
+### Flatbuffers
+
+We use Flatbuffers to define common structs and enums between TypeScript and
+Rust. These common data structures are defined in
+[msg.fbs](https://github.com/denoland/deno/blob/master/src/msg.fbs)
+
+### Updating prebuilt binaries
+
+```
+./third_party/depot_tools/upload_to_google_storage.py -b denoland \
+ -e ~/.config/gcloud/legacy_credentials/ry@tinyclouds.org/.boto `which sccache`
+mv `which sccache`.sha1 prebuilt/linux64/
+gsutil acl ch -u AllUsers:R gs://denoland/608be47bf01004aa11d4ed06955414e93934516e
+```
+
+### Continuous Benchmarks
+
+https://deno.land/benchmarks.html
+
+The benchmark chart supposes `//website/data.json` has the type
+`BenchmarkData[]` where `BenchmarkData` is defined like the below:
+
+```typescript
+interface ExecTimeData {
+ mean: number;
+ stddev: number;
+ user: number;
+ system: number;
+ min: number;
+ max: number;
+}
+
+interface BenchmarkData {
+ created_at: string;
+ sha1: string;
+ benchmark: {
+ [key: string]: ExecTimeData;
+ };
+ binarySizeData: {
+ [key: string]: number;
+ };
+ threadCountData: {
+ [key: string]: number;
+ };
+ syscallCountData: {
+ [key: string]: number;
+ };
+}
+```
+
+## Contributing
+
+[Style Guide](style_guide.html)
+
+Progress towards future releases is tracked
+[here](https://github.com/denoland/deno/milestones).
+
+Please don't make [the benchmarks](https://deno.land/benchmarks.html) worse.
+
+Ask for help in the [community chat room](https://gitter.im/denolife/Lobby).
+
+### Submitting a pull request
+
+Before submitting, please make sure the following is done:
+
+1. There are tests that cover the changes.
+2. Ensure `./tools/test.py` passes.
+3. Format your code with
+ `PYTHONPATH=third_party/python_packages deno ./tools/format.ts --allow-read --allow-run`.
+ <!-- TODO: set PYTHONPATH in format.ts when run API has env option -->
+4. Make sure `./tools/lint.py` passes.
+
+### Changes to `third_party`
+
+[`deno_third_party`](https://github.com/denoland/deno_third_party) contains most
+of the external code that Deno depends on, so that we know exactly what we are
+executing at any given time. It is carefully mantained with a mixture of manual
+labor and private scripts. It's likely you will need help from @ry or
+@piscisaureus to make changes.
+
+### Adding Ops (aka bindings)
+
+We are very concerned about making mistakes when adding new APIs. When adding an
+Op to Deno, the counterpart interfaces on other platforms should be researched.
+Please list how this functionality is done in Go, Node, Rust, and Python.
+
+As an example, see how `deno.rename()` was proposed and added in
+[PR #671](https://github.com/denoland/deno/pull/671).
+
+### Documenting APIs
+
+It is important to document public APIs and we want to do that inline with the
+code. This helps ensure that code and documentation are tightly coupled
+together.
+
+#### Utilize JSDoc
+
+All publicly exposed APIs and types, both via the `deno` module as well as the
+global/`window` namespace should have JSDoc documentation. This documentation is
+parsed and available to the TypeScript compiler, and therefore easy to provide
+further downstream. JSDoc blocks come just prior to the statement they apply to
+and are denoted by a leading `/**` before terminating with a `*/`. For example:
+
+```ts
+/** A simple JSDoc comment */
+export const FOO = "foo";
+```