mirror of
https://github.com/denoland/deno.git
synced 2024-12-21 23:04:45 -05:00
web design (#1728)
This commit is contained in:
parent
489c69f8e1
commit
a4dec944bc
20 changed files with 1407 additions and 972 deletions
98
.github/CONTRIBUTING.md
vendored
98
.github/CONTRIBUTING.md
vendored
|
@ -1,98 +0,0 @@
|
|||
# Contributing To Deno
|
||||
|
||||
Check [the roadmap](https://github.com/denoland/deno/blob/master/Roadmap.md)
|
||||
before contributing.
|
||||
|
||||
Please don't make [the benchmarks](https://denoland.github.io/deno/) worse.
|
||||
|
||||
Ask for help in the issues or on the
|
||||
[chat room](https://gitter.im/denolife/Lobby).
|
||||
|
||||
Progress towards future releases is tracked
|
||||
[here](https://github.com/denoland/deno/milestones).
|
||||
|
||||
Docs are [here](https://github.com/denoland/deno/blob/master/Docs.md).
|
||||
|
||||
## 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`
|
||||
|
||||
Changes to `third_party` including any changes in the `package.json` will impact
|
||||
the [denoland/deno_third_party](https://github.com/denoland/deno_third_party)
|
||||
repository as well.
|
||||
|
||||
## 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";
|
||||
```
|
||||
|
||||
### JSDoc style guide
|
||||
|
||||
- It is important that documentation is easily human readable, but there is also
|
||||
a need to provide additional styling information to ensure generated
|
||||
documentation is more rich text. Therefore JSDoc should generally follow
|
||||
markdown markup to enrich the text.
|
||||
- While markdown supports HTML tags, it is forbidden in JSDoc blocks.
|
||||
- Code string literals should be braced with the back-tick (\`) instead of
|
||||
quotes. For example:
|
||||
```ts
|
||||
/** Import something from the `deno` module. */
|
||||
```
|
||||
- Do not document function arguments unless they are non-obvious of their intent
|
||||
(though if they are non-obvious intent, the API should be considered anyways).
|
||||
Therefore `@param` should generally not be used.
|
||||
- Vertical spacing should be minimized whenever possible. Therefore single line
|
||||
comments should be written as:
|
||||
```ts
|
||||
/** This is a good single line JSDoc */
|
||||
```
|
||||
And not:
|
||||
```ts
|
||||
/**
|
||||
* This is a bad single line JSDoc
|
||||
*/
|
||||
```
|
||||
- Code examples should not utilise the triple-back tick (\`\`\`) notation or
|
||||
tags. They should just be marked by indentation, which requires a break before
|
||||
the block and 6 additional spaces for each line of the example. This is 4 more
|
||||
than the first column of the comment. For example:
|
||||
```ts
|
||||
/** A straight forward comment and an example:
|
||||
*
|
||||
* import { foo } from "deno";
|
||||
* foo("bar");
|
||||
*/
|
||||
```
|
||||
- Code examples should not contain additional comments. It is already inside a
|
||||
comment. If it needs further comments is not a good example.
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,3 +1,3 @@
|
|||
<!--
|
||||
https://github.com/denoland/deno/blob/master/.github/CONTRIBUTING.md
|
||||
Before submitting a PR read https://deno.land/manual.html#contributing
|
||||
-->
|
||||
|
|
440
Docs.md
440
Docs.md
|
@ -1,439 +1 @@
|
|||
# Deno Documentation
|
||||
|
||||
## 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!
|
||||
|
||||
## 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.
|
||||
|
||||
Try it:
|
||||
|
||||
```
|
||||
> deno https://deno.land/thumb.ts
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
To get an exact reference of deno's runtime API, run the following in the
|
||||
command line:
|
||||
|
||||
```
|
||||
> deno --types
|
||||
```
|
||||
|
||||
Or see the [doc website](https://deno.land/typedoc/index.html).
|
||||
|
||||
If you are embedding deno in a Rust program, see
|
||||
[the rust docs](https://deno.land/rustdoc/deno/index.html).
|
||||
|
||||
## Build Instructions
|
||||
|
||||
### 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`.
|
||||
|
||||
### Build:
|
||||
|
||||
# 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.
|
||||
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 -->
|
||||
|
||||
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`.
|
||||
|
||||
## Tutorial
|
||||
|
||||
### 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.
|
||||
|
||||
### 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.
|
||||
|
||||
## 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`.
|
||||
|
||||
## 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.
|
||||
|
||||
## Useful command line flags
|
||||
|
||||
V8 has many many command-line flags, that you can see with `--v8-options`. Here
|
||||
are a few particularly useful ones:
|
||||
|
||||
```
|
||||
--async-stack-traces
|
||||
```
|
||||
|
||||
## How to Profile deno
|
||||
|
||||
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)
|
||||
|
||||
## How to Debug deno
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
## Internals
|
||||
|
||||
### Internal: libdeno API.
|
||||
|
||||
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:
|
||||
https://github.com/denoland/deno/blob/master/libdeno/deno.h
|
||||
https://github.com/denoland/deno/blob/master/js/libdeno.ts
|
||||
|
||||
### Internal: Flatbuffers provide shared data between Rust and V8
|
||||
|
||||
We use Flatbuffers to define common structs and enums between TypeScript and
|
||||
Rust. These common data structures are defined in
|
||||
https://github.com/denoland/deno/blob/master/src/msg.fbs
|
||||
|
||||
### Internal: 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
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
See
|
||||
[CONTRIBUTING.md](https://github.com/denoland/deno/blob/master/.github/CONTRIBUTING.md).
|
||||
Moved to https://deno.land/manual.html
|
||||
|
|
86
README.md
86
README.md
|
@ -4,91 +4,7 @@
|
|||
| :------------------------: | :------------------------: |
|
||||
| [![][tci badge]][tci link] | [![][avy badge]][avy link] |
|
||||
|
||||
## A new way to JavaScript.
|
||||
|
||||
- Supports TypeScript out of the box. Uses a recent version of V8. That is, it's
|
||||
very modern JavaScript.
|
||||
|
||||
- No `package.json`. No npm. Not explicitly compatible with Node.
|
||||
|
||||
- Imports reference source code URLs only.
|
||||
|
||||
```typescript
|
||||
import { test } from "https://unpkg.com/deno_testing@0.0.5/testing.ts";
|
||||
import { log } from "./util.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.)
|
||||
|
||||
- File system and network access can be controlled in order to run sandboxed
|
||||
code. Defaults to read-only file system access and no network access. 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. To enable write access explicitly use `--allow-write`
|
||||
and `--allow-net` for network access.
|
||||
|
||||
- Single executable:
|
||||
|
||||
```
|
||||
> ls -lh target/release/deno
|
||||
-rwxr-xr-x 1 rld staff 48M Aug 2 13:24 target/release/deno
|
||||
> otool -L target/release/deno
|
||||
target/release/deno:
|
||||
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
|
||||
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
|
||||
/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 58286.51.6)
|
||||
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
|
||||
>
|
||||
```
|
||||
|
||||
- Always dies on uncaught errors.
|
||||
|
||||
- [Aims to support top-level `await`.](https://github.com/denoland/deno/issues/471)
|
||||
|
||||
- Aims to be browser compatible.
|
||||
|
||||
See the website for more info [deno.land](https://deno.land).
|
||||
|
||||
## Install
|
||||
|
||||
With Shell:
|
||||
|
||||
```
|
||||
curl -L https://deno.land/x/install/install.sh | bash
|
||||
```
|
||||
|
||||
With 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
|
||||
```
|
||||
|
||||
Try it:
|
||||
|
||||
```
|
||||
> deno https://deno.land/thumb.ts
|
||||
```
|
||||
|
||||
See [deno_install](https://github.com/denoland/deno_install) for more
|
||||
installation methods..
|
||||
|
||||
## Build locally (advanced users only)
|
||||
|
||||
For instructions to build this project locally, please see
|
||||
[the docs](https://github.com/denoland/deno/blob/master/Docs.md#build-instructions-for-advanced-users-only).
|
||||
See documentation at https://deno.land/
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
[avy badge]: https://ci.appveyor.com/api/projects/status/yel7wtcqwoy0to8x?branch=master&svg=true
|
||||
|
|
61
Roadmap.md
61
Roadmap.md
|
@ -1,61 +0,0 @@
|
|||
# Deno Roadmap
|
||||
|
||||
API and Feature requests should be submitted as PRs to this document.
|
||||
|
||||
## Security Model (partially implemented)
|
||||
|
||||
- We want to be secure by default; user should be able to run untrusted code,
|
||||
like the web.
|
||||
- Threat model:
|
||||
- Modifiying/deleting local files
|
||||
- Leaking private information
|
||||
- Disallowed default:
|
||||
- Network access
|
||||
- Local write access
|
||||
- Non-JS extensions
|
||||
- Subprocesses
|
||||
- Env access
|
||||
- Allowed default:
|
||||
- Local read access.
|
||||
- argv, stdout, stderr, stdin access always allowed.
|
||||
- Maybe: temp dir write access. (But what if they create symlinks there?)
|
||||
- The user gets prompted when the software tries to do something it doesn't have
|
||||
the privilege for.
|
||||
- Have an option to get a stack trace when access is requested.
|
||||
- Worried that granting access per file will give a false sense of security due
|
||||
to monkey patching techniques. Access should be granted per program (js
|
||||
context).
|
||||
|
||||
Example security prompts. Options are: YES, NO, PRINT STACK
|
||||
|
||||
```
|
||||
Program requests write access to "~/.ssh/id_rsa". Grant? [yNs]
|
||||
http://gist.github.com/asdfasd.js requests network access to "www.facebook.com". Grant? [yNs]
|
||||
Program requests access to environment variables. Grant? [yNs]
|
||||
Program requests to spawn `rm -rf /`. Grant? [yNs]
|
||||
```
|
||||
|
||||
- cli flags to grant access ahead of time --allow-all --allow-write --allow-net
|
||||
--allow-env --allow-exec
|
||||
- in version two we will add ability to give finer grain access
|
||||
--allow-net=facebook.com
|
||||
|
||||
## Top-level Await (Not Implemented)
|
||||
|
||||
[#471](https://github.com/denoland/deno/issues/471)
|
||||
|
||||
This will be put off until at least deno2 Milestone1 is complete. One of the
|
||||
major problems is that top-level await calls are not syntactically valid
|
||||
TypeScript.
|
||||
|
||||
### [Broken] List dependencies of a program.
|
||||
|
||||
Currently broken: https://github.com/denoland/deno/issues/1011
|
||||
|
||||
```
|
||||
% deno --deps http://gist.com/blah.js
|
||||
http://gist.com/blah.js
|
||||
http://gist.com/dep.js
|
||||
https://github.com/denoland/deno/master/testing.js
|
||||
%
|
||||
```
|
|
@ -61,7 +61,7 @@ async function run(...args: string[]): Promise<void> {
|
|||
"--allow-write",
|
||||
"js/deps/https/deno.land/x/std/prettier/main.ts",
|
||||
"rollup.config.js",
|
||||
...findFiles(["."], [".json", ".md"], { depth: 1 }),
|
||||
...findFiles([".", "website"], [".json", ".md"], { depth: 1 }),
|
||||
...findFiles(
|
||||
[".github", "js", "tests", "tools", "website"],
|
||||
[".js", ".json", ".ts", ".md"],
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
## About benchmark data
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
```
|
|
@ -1,44 +0,0 @@
|
|||
<!-- Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>all benchmark data | deno</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/c3@0.6.7/c3.min.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<meta content='width=device-width, initial-scale=1.0' name='viewport' />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>all benchmark data</h1>
|
||||
|
||||
<p><a href="./">back</a>
|
||||
|
||||
<h2>Execution time</h2>
|
||||
<div id="exec-time-chart"></div>
|
||||
|
||||
<h2>Throughput</h2>
|
||||
<div id="throughput-chart"></div>
|
||||
|
||||
<h2>Req/Sec</h2>
|
||||
<div id="req-per-sec-chart"></div>
|
||||
|
||||
<h2>Executable size</h2>
|
||||
<div id="binary-size-chart"></div>
|
||||
|
||||
<h2>Thread count</h2>
|
||||
<div id="thread-count-chart"></div>
|
||||
|
||||
<h2>Syscall count</h2>
|
||||
<div id="syscall-count-chart"></div>
|
||||
</main>
|
||||
<script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script>
|
||||
<script src="https://unpkg.com/c3@0.6.7/c3.min.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { drawCharts } from "./app.js";
|
||||
window.chartWidth = 800
|
||||
drawCharts("./data.json");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -126,6 +126,7 @@ function generate(
|
|||
) {
|
||||
const yAxis = {
|
||||
padding: { bottom: 0 },
|
||||
min: 0,
|
||||
label: yLabel
|
||||
};
|
||||
if (yTickFormat) {
|
||||
|
@ -133,6 +134,7 @@ function generate(
|
|||
format: yTickFormat
|
||||
};
|
||||
if (yTickFormat == logScale) {
|
||||
delete yAxis.min;
|
||||
for (let col of columns) {
|
||||
for (let i = 1; i < col.length; i++) {
|
||||
if (col[i] == null) {
|
||||
|
@ -221,7 +223,7 @@ export async function drawChartsFromBenchmarkData(dataUrl) {
|
|||
}
|
||||
|
||||
gen("#exec-time-chart", execTimeColumns, "seconds", logScale);
|
||||
gen("#throughput-chart", throughputColumns, "seconds");
|
||||
gen("#throughput-chart", throughputColumns, "seconds", logScale);
|
||||
gen("#req-per-sec-chart", reqPerSecColumns, "1000 req/sec", formatReqSec);
|
||||
gen("#binary-size-chart", binarySizeColumns, "megabytes", formatMB);
|
||||
gen("#thread-count-chart", threadCountColumns, "threads");
|
||||
|
|
137
website/benchmarks.html
Normal file
137
website/benchmarks.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<!-- Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Deno Benchmarks</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/c3@0.6.7/c3.min.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Deno Continuous Benchmarks</h1>
|
||||
|
||||
<p>
|
||||
These plots are updated on every commit to
|
||||
<a href="https://github.com/denoland/deno">master branch</a>.
|
||||
</p>
|
||||
|
||||
<p><a href="#recent">recent data</a></p>
|
||||
<p><a href="#all">all data</a> (takes a moment to load)</p>
|
||||
|
||||
<h3 id="exec-time">Execution time <a href="#exec-time">#</a></h3>
|
||||
<p>
|
||||
This shows how much time total it takes to run a few simple deno
|
||||
programs:
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tests/002_hello.ts"
|
||||
>
|
||||
tests/002_hello.ts
|
||||
</a>
|
||||
and
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tests/003_relative_import.ts"
|
||||
>tests/003_relative_import.ts</a
|
||||
>. For deno to execute typescript, it must first compile it to JS. A
|
||||
warm startup is when deno has a cached JS output already, so it should
|
||||
be fast because it bypasses the TS compiler. A cold startup is when deno
|
||||
must compile from scratch.
|
||||
</p>
|
||||
<div id="exec-time-chart"></div>
|
||||
|
||||
<h3 id="throughput">Throughput <a href="#throughput">#</a></h3>
|
||||
|
||||
<p>
|
||||
Time it takes to pipe a certain amount of data through Deno.
|
||||
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tests/echo_server.ts"
|
||||
>
|
||||
echo_server.ts
|
||||
</a>
|
||||
and
|
||||
<a href="https://github.com/denoland/deno/blob/master/tests/cat.ts">
|
||||
cat.ts </a
|
||||
>. Smaller is better.
|
||||
</p>
|
||||
|
||||
<div id="throughput-chart"></div>
|
||||
|
||||
<h3 id="req-per-sec">Req/Sec <a href="#req-per-sec">#</a></h3>
|
||||
|
||||
<p>
|
||||
Tests HTTP server performance. 10 keep-alive connections do as many
|
||||
hello-world requests as possible. Bigger is better.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<!-- TODO rename "deno" to "deno_tcp". -->
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tests/http_bench.ts"
|
||||
>
|
||||
deno
|
||||
</a>
|
||||
is a fake http server that doesn't parse HTTP. It is comparable to
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tools/node_tcp.js"
|
||||
>
|
||||
node_tcp
|
||||
</a>
|
||||
.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/denoland/deno_std/blob/master/http/http_bench.ts"
|
||||
>
|
||||
deno_net_http
|
||||
</a>
|
||||
is a web server written in TypeScript. It is comparable to
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tools/node_http.js"
|
||||
>
|
||||
node_http
|
||||
</a>
|
||||
.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tools/hyper_hello.rs"
|
||||
>
|
||||
hyper
|
||||
</a>
|
||||
is a Rust HTTP server and represents an upper bound.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div id="req-per-sec-chart"></div>
|
||||
|
||||
<h3 id="size">Executable size <a href="#size">#</a></h3>
|
||||
<p>deno ships only a single binary. We track its size here.</p>
|
||||
<div id="binary-size-chart"></div>
|
||||
|
||||
<h3 id="threads">Thread count <a href="#threads">#</a></h3>
|
||||
<p>How many threads various programs use.</p>
|
||||
<div id="thread-count-chart"></div>
|
||||
|
||||
<h3 id="syscalls">Syscall count <a href="#syscalls">#</a></h3>
|
||||
<p>
|
||||
How many total syscalls are performed when executing a given script.
|
||||
</p>
|
||||
<div id="syscall-count-chart"></div>
|
||||
</main>
|
||||
<script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script>
|
||||
<script src="https://unpkg.com/c3@0.6.7/c3.min.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { drawCharts } from "./app.js";
|
||||
window.chartWidth = 800;
|
||||
|
||||
let u = window.location.hash.match("all") ? "./data.json" : "recent.json";
|
||||
|
||||
drawCharts(u);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -3,26 +3,21 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Deno</title>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/c3@0.6.7/c3.min.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
||||
name="viewport"
|
||||
/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<img id="logo" src="deno_logo_2.gif" width="150" />
|
||||
<!-- Logo by hashrock https://denolib.github.io/animated-deno-logo/ -->
|
||||
|
||||
<header>
|
||||
<a href="https://github.com/denolib/animated-deno-logo/"
|
||||
><img id="logo" src="deno_logo_2.gif" width="150"
|
||||
/></a>
|
||||
<!-- Logo by hashrock -->
|
||||
<div>
|
||||
<h1>Deno</h1>
|
||||
|
||||
<p>
|
||||
A new way to JavaScript
|
||||
|
||||
<!-- TODO(ry) add the registry badges. -->
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -31,30 +26,32 @@
|
|||
<th>Windows</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="https://github.com/denoland/deno">deno</a>
|
||||
</th>
|
||||
<th><a href="https://github.com/denoland/deno">deno</a></th>
|
||||
<td>
|
||||
<a class="badge" href="https://travis-ci.com/denoland/deno">
|
||||
<img src="https://travis-ci.com/denoland/deno.svg?branch=master"/>
|
||||
<img
|
||||
src="https://travis-ci.com/denoland/deno.svg?branch=master"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="badge" href="https://ci.appveyor.com/project/deno/deno">
|
||||
<img src="https://ci.appveyor.com/api/projects/status/yel7wtcqwoy0to8x/branch/master?svg=true"/>
|
||||
<img
|
||||
src="https://ci.appveyor.com/api/projects/status/yel7wtcqwoy0to8x/branch/master?svg=true"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="https://github.com/denoland/deno_std">deno_std</a>
|
||||
</th>
|
||||
<th><a href="https://github.com/denoland/deno_std">deno_std</a></th>
|
||||
<td colspan="2">
|
||||
<a
|
||||
class="badge"
|
||||
href="https://dev.azure.com/denoland/deno_std/_build?definitionId=2"
|
||||
>
|
||||
<img src="https://dev.azure.com/denoland/deno_std/_apis/build/status/denoland.deno_std?branchName=master"/>
|
||||
<img
|
||||
src="https://dev.azure.com/denoland/deno_std/_apis/build/status/denoland.deno_std?branchName=master"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -64,7 +61,9 @@
|
|||
</th>
|
||||
<td>
|
||||
<a class="badge" href="https://travis-ci.com/denoland/deno_install">
|
||||
<img src="https://travis-ci.com/denoland/deno_install.svg?branch=master"/>
|
||||
<img
|
||||
src="https://travis-ci.com/denoland/deno_install.svg?branch=master"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
|
@ -72,166 +71,73 @@
|
|||
class="badge"
|
||||
href="https://ci.appveyor.com/project/deno/deno-install"
|
||||
>
|
||||
<img src="https://ci.appveyor.com/api/projects/status/gtekeaf7r60xa896?branch=master&svg=true"/>
|
||||
<img
|
||||
src="https://ci.appveyor.com/api/projects/status/gtekeaf7r60xa896?branch=master&svg=true"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="https://github.com/denoland/registry">registry</a>
|
||||
</th>
|
||||
<th><a href="https://github.com/denoland/registry">registry</a></th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2 id="install"><a href="#install">#</a>Install</h2>
|
||||
<h2 id="install">Install <a href="#install">#</a></h2>
|
||||
|
||||
<p>With Shell</p>
|
||||
<pre>curl -fL https://deno.land/x/install/install.sh | sh</pre>
|
||||
<p>With PowerShell</p>
|
||||
<pre>iex (iwr https://deno.land/x/install/install.ps1)</pre>
|
||||
<p>Mac or Linux</p>
|
||||
<pre>curl -fL <a
|
||||
href="https://github.com/denoland/deno_install/blob/master/install.sh">https://deno.land/x/install/install.sh</a> | sh</pre>
|
||||
<p>Windows (PowerShell)</p>
|
||||
<pre>iex (iwr <a
|
||||
href="https://github.com/denoland/deno_install/blob/master/install.ps1">https://deno.land/x/install/install.ps1</a>)</pre>
|
||||
|
||||
<h2 id="mini-tutorial"><a href="#mini-tutorial">#</a>Mini-tutorial</h2>
|
||||
<h2 id="example">Example <a href="#example">#</a></h2>
|
||||
|
||||
<p>Try running a simple program:</p>
|
||||
<pre>deno https://deno.land/welcome.js</pre>
|
||||
|
||||
<p>Or a more complex one:</p>
|
||||
|
||||
<p>Try a Deno program. This one serves a local directory in HTTP.</p>
|
||||
<pre>
|
||||
alias file_server="deno \
|
||||
https://deno.land/x/http/file_server.ts --allow-net"
|
||||
</pre>
|
||||
import { serve } from "<a
|
||||
href="https://github.com/denoland/deno_std/blob/master/http/server.ts">https://deno.land/x/http/server.ts</a>";
|
||||
const s = serve("0.0.0.0:8000");
|
||||
|
||||
<p>Run it:</p>
|
||||
<pre>
|
||||
% file_server .
|
||||
Downloading https://deno.land/x/http/file_server.ts...
|
||||
[...]
|
||||
HTTP server listening on http://0.0.0.0:4500/
|
||||
</pre>
|
||||
<p>And if you ever want to upgrade to the latest published version:</p>
|
||||
<pre>file_server --reload</pre>
|
||||
async function main() {
|
||||
for await (const req of s) {
|
||||
req.respond({ body: new TextEncoder().encode("Hello World\n") });
|
||||
}
|
||||
}
|
||||
|
||||
<h2 id="dig-in"><a href="#dig-in">#</a>Dig in...</h2>
|
||||
main(); </pre>
|
||||
|
||||
<a href="https://github.com/denoland/deno/blob/master/Docs.md">
|
||||
Documentation
|
||||
</a>
|
||||
<h2 id="dig-in">Dig in... <a href="#dig-in">#</a></h2>
|
||||
|
||||
<p>
|
||||
<a href="typedoc/index.html">API Reference</a>
|
||||
<b><a href="manual.html">Manual</a></b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/denolib/awesome-deno">
|
||||
Links to other Deno resources.
|
||||
</a>
|
||||
</p>
|
||||
<p><a href="https://deno.land/typedoc">API Reference</a></p>
|
||||
|
||||
<h2 id="benchmarks"><a href="#benchmarks">#</a>Continuous Benchmarks</h2>
|
||||
<p><a href="style_guide.html">Style Guide</a></p>
|
||||
|
||||
<p>These plots are updated on every commit to</p>
|
||||
<p>
|
||||
<a href="https://github.com/denoland/deno">master branch</a>
|
||||
</p>
|
||||
<p><a href="https://deno.land/x/">Module repository</a></p>
|
||||
|
||||
<h3 id="exec-time"><a href="#exec-time">#</a>Execution time</h3>
|
||||
<p>This shows how much time total it takes to run a few simple deno programs:</p>
|
||||
<a href="https://github.com/denoland/deno/blob/master/tests/002_hello.ts">
|
||||
tests/002_hello.ts
|
||||
</a>
|
||||
<p>and</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://github.com/denoland/deno/blob/master/tests/003_relative_import.ts"
|
||||
<a href="https://github.com/denoland/deno/blob/master/Releases.md"
|
||||
>Release notes</a
|
||||
>
|
||||
tests/003_relative_import.ts
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
For deno to execute typescript, it must first compile it to JS. A warm
|
||||
startup is when deno has a cached JS output already, so it should be fast
|
||||
because it bypasses the TS compiler. A cold startup is when deno must
|
||||
compile from scratch.
|
||||
</p>
|
||||
<div id="exec-time-chart"></div>
|
||||
|
||||
<h3 id="throughput"><a href="#throughput">#</a>Throughput</h3>
|
||||
|
||||
<p>Time it takes to pipe a certain amount of data through Deno.</p>
|
||||
|
||||
<a href="https://github.com/denoland/deno/blob/master/tests/echo_server.ts">
|
||||
echo_server.ts
|
||||
</a>
|
||||
<p>and</p>
|
||||
<a href="https://github.com/denoland/deno/blob/master/tests/cat.ts">
|
||||
cat.ts
|
||||
</a>
|
||||
<p>Smaller is better.</p>
|
||||
|
||||
<div id="throughput-chart"></div>
|
||||
|
||||
<h3 id="req-per-sec"><a href="#req-per-sec">#</a>Req/Sec</h3>
|
||||
|
||||
<p>
|
||||
Tests HTTP server performance. 10 keep-alive connections do as many
|
||||
hello-world requests as possible. Bigger is better.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<!-- TODO rename "deno" to "deno_tcp". -->
|
||||
<li>
|
||||
<a href="https://github.com/denoland/deno/blob/master/tests/http_bench.ts">
|
||||
deno
|
||||
</a>
|
||||
is a fake http server that doesn't parse HTTP. It is comparable to
|
||||
<a href="https://github.com/denoland/deno/blob/master/tools/node_tcp.js">
|
||||
node_tcp
|
||||
</a>
|
||||
.
|
||||
</li>
|
||||
<p><a href="https://gitter.im/denolife/Lobby">Community chat room</a></p>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/denoland/deno_std/blob/master/http/http_bench.ts">
|
||||
deno_net_http
|
||||
</a>
|
||||
is a web server written in TypeScript. It is comparable to
|
||||
<a href="https://github.com/denoland/deno/blob/master/tools/node_http.js">
|
||||
node_http
|
||||
</a>
|
||||
.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/denoland/deno/blob/master/tools/hyper_hello.rs">
|
||||
hyper
|
||||
</a>
|
||||
is a Rust HTTP server and represents an upper bound.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div id="req-per-sec-chart"></div>
|
||||
|
||||
<h3 id="size"><a href="#size">#</a>Executable size</h3>
|
||||
<p>deno ships only a single binary. We track its size here.</p>
|
||||
<div id="binary-size-chart"></div>
|
||||
|
||||
<h3 id="threads"><a href="#threads">#</a>Thread count</h3>
|
||||
<p>How many threads various programs use.</p>
|
||||
<div id="thread-count-chart"></div>
|
||||
|
||||
<h3 id="syscalls"><a href="#syscalls">#</a>Syscall count</h3>
|
||||
<p>How many total syscalls are performed when executing a given script.</p>
|
||||
<div id="syscall-count-chart"></div>
|
||||
<p><a href="benchmarks.html">Benchmarks</a></p>
|
||||
|
||||
<p>
|
||||
<a href="./all_benchmark.html">Historical benchmark data</a>
|
||||
<a href="https://github.com/denolib/awesome-deno"
|
||||
>A curated list of awesome Deno things</a
|
||||
>
|
||||
</p>
|
||||
</main>
|
||||
|
||||
<script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script>
|
||||
<script src="https://unpkg.com/c3@0.6.7/c3.min.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { drawCharts } from "./app.js";
|
||||
|
||||
drawCharts("recent.json");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"dir": "ltr",
|
||||
"lang": "en",
|
||||
"name": "Deno",
|
||||
"scope": "/",
|
||||
"display": "browser",
|
||||
"start_url": "/",
|
||||
"short_name": "Deno",
|
||||
"theme_color": "#F0F0F0",
|
||||
"description": "A new way to JavaScript",
|
||||
"orientation": "any",
|
||||
"background_color": "#F0F0F0"
|
||||
}
|
40
website/manual.html
Normal file
40
website/manual.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<!-- Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Deno Manual</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div id="manual"></div>
|
||||
|
||||
<script src="https://unpkg.com/showdown@1.9.0/dist/showdown.js"></script>
|
||||
<script src="showdown_toc.js"></script>
|
||||
<script>
|
||||
const url = "manual.md";
|
||||
|
||||
async function main() {
|
||||
const response = await fetch(url);
|
||||
const content = await response.text();
|
||||
|
||||
let converter = new showdown.Converter({ extensions: ["toc"] });
|
||||
let html = converter.makeHtml(content);
|
||||
|
||||
const manual = document.getElementById("manual");
|
||||
manual.innerHTML = html;
|
||||
|
||||
// To make anchor links work properly, we have to manually scroll
|
||||
// since the markdown is rendered dynamically.
|
||||
if (window.location.hash) {
|
||||
let el = document.getElementById(window.location.hash.slice(1));
|
||||
window.scrollTo({ top: el.offsetTop });
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
</script>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
656
website/manual.md
Normal file
656
website/manual.md
Normal file
|
@ -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";
|
||||
```
|
BIN
website/schematic_v0.2.png
Normal file
BIN
website/schematic_v0.2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
142
website/showdown_toc.js
Normal file
142
website/showdown_toc.js
Normal file
|
@ -0,0 +1,142 @@
|
|||
// Extension loading compatible with AMD and CommonJs
|
||||
(function(extension) {
|
||||
"use strict";
|
||||
|
||||
if (typeof showdown === "object") {
|
||||
// global (browser or nodejs global)
|
||||
showdown.extension("toc", extension());
|
||||
} else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define("toc", extension());
|
||||
} else if (typeof exports === "object") {
|
||||
// Node, CommonJS-like
|
||||
module.exports = extension();
|
||||
} else {
|
||||
// showdown was not found so we throw
|
||||
throw Error("Could not find showdown library");
|
||||
}
|
||||
})(function() {
|
||||
function getHeaderEntries(sourceHtml) {
|
||||
if (typeof window === "undefined") {
|
||||
return getHeaderEntriesInNodeJs(sourceHtml);
|
||||
} else {
|
||||
return getHeaderEntriesInBrowser(sourceHtml);
|
||||
}
|
||||
}
|
||||
|
||||
function getHeaderEntriesInNodeJs(sourceHtml) {
|
||||
var cheerio = require("cheerio");
|
||||
var $ = cheerio.load(sourceHtml);
|
||||
var headers = $("h1, h2, h3, h4, h5, h6");
|
||||
|
||||
var headerList = [];
|
||||
for (var i = 0; i < headers.length; i++) {
|
||||
var el = headers[i];
|
||||
headerList.push(new TocEntry(el.name, $(el).text(), $(el).attr("id")));
|
||||
}
|
||||
|
||||
return headerList;
|
||||
}
|
||||
|
||||
function getHeaderEntriesInBrowser(sourceHtml) {
|
||||
// Generate dummy element
|
||||
var source = document.createElement("div");
|
||||
source.innerHTML = sourceHtml;
|
||||
|
||||
// Find headers
|
||||
var headers = source.querySelectorAll("h1, h2, h3, h4, h5, h6");
|
||||
var headerList = [];
|
||||
for (var i = 0; i < headers.length; i++) {
|
||||
var el = headers[i];
|
||||
headerList.push(new TocEntry(el.tagName, el.textContent, el.id));
|
||||
}
|
||||
|
||||
return headerList;
|
||||
}
|
||||
|
||||
function TocEntry(tagName, text, anchor) {
|
||||
this.tagName = tagName;
|
||||
this.text = text;
|
||||
this.anchor = anchor;
|
||||
this.children = [];
|
||||
}
|
||||
|
||||
TocEntry.prototype.childrenToString = function() {
|
||||
if (this.children.length === 0) {
|
||||
return "";
|
||||
}
|
||||
var result = "<ul>\n";
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
result += this.children[i].toString();
|
||||
}
|
||||
result += "</ul>\n";
|
||||
return result;
|
||||
};
|
||||
|
||||
TocEntry.prototype.toString = function() {
|
||||
var result = "<li>";
|
||||
if (this.text) {
|
||||
result += '<a href="#' + this.anchor + '">' + this.text + "</a>";
|
||||
}
|
||||
result += this.childrenToString();
|
||||
result += "</li>\n";
|
||||
return result;
|
||||
};
|
||||
|
||||
function sortHeader(tocEntries, level) {
|
||||
level = level || 1;
|
||||
var tagName = "H" + level,
|
||||
result = [],
|
||||
currentTocEntry;
|
||||
|
||||
function push(tocEntry) {
|
||||
if (tocEntry !== undefined) {
|
||||
if (tocEntry.children.length > 0) {
|
||||
tocEntry.children = sortHeader(tocEntry.children, level + 1);
|
||||
}
|
||||
result.push(tocEntry);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < tocEntries.length; i++) {
|
||||
var tocEntry = tocEntries[i];
|
||||
if (tocEntry.tagName.toUpperCase() !== tagName) {
|
||||
if (currentTocEntry === undefined) {
|
||||
currentTocEntry = new TocEntry();
|
||||
}
|
||||
currentTocEntry.children.push(tocEntry);
|
||||
} else {
|
||||
push(currentTocEntry);
|
||||
currentTocEntry = tocEntry;
|
||||
}
|
||||
}
|
||||
|
||||
push(currentTocEntry);
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
type: "output",
|
||||
filter: function(sourceHtml) {
|
||||
var headerList = getHeaderEntries(sourceHtml);
|
||||
|
||||
// No header found
|
||||
if (headerList.length === 0) {
|
||||
return sourceHtml;
|
||||
}
|
||||
|
||||
// Sort header
|
||||
headerList = sortHeader(headerList);
|
||||
|
||||
// Skip the title.
|
||||
if (headerList.length == 1) {
|
||||
headerList = headerList[0].children;
|
||||
}
|
||||
|
||||
// Build result and replace all [toc]
|
||||
var result =
|
||||
'<div class="toc">\n<ul>\n' + headerList.join("") + "</ul>\n</div>\n";
|
||||
return sourceHtml.replace(/\[toc\]/gi, result);
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,74 +1,91 @@
|
|||
|
||||
body {
|
||||
color: #111;
|
||||
color: #444;
|
||||
background: #f0f0f0;
|
||||
margin: 1em;
|
||||
font-family: Arial;
|
||||
font-size: 20px;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1.5;
|
||||
font-family: sans-serif;
|
||||
|
||||
margin: 5ex 10ex;
|
||||
max-width: 80ex;
|
||||
}
|
||||
|
||||
main {
|
||||
#manual img {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: normal;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, p, table {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
td, th {
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
border: 1px dotted #bbb;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin: 0px auto;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #333;
|
||||
}
|
||||
a:hover {
|
||||
color: #488;
|
||||
color: #106ad5;
|
||||
}
|
||||
|
||||
a.badge {
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
height: 20px;
|
||||
transition: .3s box-shadow;
|
||||
}
|
||||
a.badge:hover {
|
||||
box-shadow: 0 0 5px 0 #333;
|
||||
pre a {
|
||||
color: #001631;
|
||||
}
|
||||
|
||||
a[href^="#"] { /* Hash links */
|
||||
text-decoration: none;
|
||||
h2 a, h3 a {
|
||||
display: none;
|
||||
color: #3bace5;
|
||||
margin-right: 0.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
a[href^="#"]:hover {
|
||||
text-decoration: underline;
|
||||
color: #3d9bcc;
|
||||
|
||||
h2:hover a,
|
||||
h3:hover a {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #ddd;
|
||||
/* background: rgba(36, 126, 233, 0.03); */
|
||||
color: #161616;
|
||||
background: rgba(36, 126, 233, 0.1);
|
||||
padding: 15px;
|
||||
word-wrap: normal;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 16px 4px;
|
||||
}
|
||||
|
||||
td, th {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border: 1px solid #aaa;
|
||||
padding: 6px;
|
||||
header > * {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-device-width: 480px) {
|
||||
|
||||
main {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
40
website/style_guide.html
Normal file
40
website/style_guide.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<!-- Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Deno Style Guide</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div id="manual"></div>
|
||||
|
||||
<script src="https://unpkg.com/showdown@1.9.0/dist/showdown.js"></script>
|
||||
<script src="showdown_toc.js"></script>
|
||||
<script>
|
||||
const url = "style_guide.md";
|
||||
|
||||
async function main() {
|
||||
const response = await fetch(url);
|
||||
const content = await response.text();
|
||||
|
||||
let converter = new showdown.Converter({ extensions: ["toc"] });
|
||||
let html = converter.makeHtml(content);
|
||||
|
||||
const manual = document.getElementById("manual");
|
||||
manual.innerHTML = html;
|
||||
|
||||
// To make anchor links work properly, we have to manually scroll
|
||||
// since the markdown is rendered dynamically.
|
||||
if (window.location.hash) {
|
||||
let el = document.getElementById(window.location.hash.slice(1));
|
||||
window.scrollTo({ top: el.offsetTop });
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
</script>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
264
website/style_guide.md
Normal file
264
website/style_guide.md
Normal file
|
@ -0,0 +1,264 @@
|
|||
# Deno Style Guide
|
||||
|
||||
[toc]
|
||||
|
||||
## Use TypeScript
|
||||
|
||||
## Use the term "module" instead of "library" or "package"
|
||||
|
||||
For clarity and consistency avoid the terms "library" and "package". Instead use
|
||||
"module" to refer to a single JS or TS file and also to refer to a directory of
|
||||
TS/JS code.
|
||||
|
||||
## Do not use the filename `index.ts` nor `index.js`
|
||||
|
||||
Deno does not treat "index.js" or "index.ts" in a special way. By using these
|
||||
filenames, it suggests that they can be left out of the module specifier when
|
||||
they cannot. This is confusing.
|
||||
|
||||
If a directory of code needs a default entry point, use the filename `mod.ts`.
|
||||
The filename `mod.ts` follows Rust’s convention, is shorter than `index.ts`, and
|
||||
doesn’t come with any preconceived notions about how it might work.
|
||||
|
||||
## Within `deno_std`, do not depend on external code
|
||||
|
||||
`deno_std` is intended to be baseline functionality that all Deno programs can
|
||||
rely on. We want to guarantee to users that this code does not include
|
||||
potentially unreviewed third party code.
|
||||
|
||||
## Within `deno_std`, minimize dependencies; do not make circular imports.
|
||||
|
||||
Although `deno_std` is a standalone codebase, we must still be careful to keep
|
||||
the internal dependencies simple and manageable. In particular, be careful to
|
||||
not to introduce circular imports.
|
||||
|
||||
## For consistency, use underscores, not dashes in filenames.
|
||||
|
||||
Example: Instead of `file-server.ts` use `file_server.ts`.
|
||||
|
||||
## Format code according using prettier.
|
||||
|
||||
More specifically, code should be wrapped at 80 columns and use 2-space
|
||||
indentation and use camel-case. Use `//format.ts` to invoke prettier.
|
||||
|
||||
## Exported functions: max 2 args, put the rest into an options object.
|
||||
|
||||
When designing function interfaces, stick to the following rules.
|
||||
|
||||
1. A function that is part of the public API takes 0-2 required arguments, plus
|
||||
(if necessary) an options object (so max 3 total).
|
||||
|
||||
2. Optional parameters should generally go into the options object.
|
||||
|
||||
An optional parameter that's not in an options object might be acceptable if
|
||||
there is only one, and it seems inconceivable that we would add more optional
|
||||
parameters in the future.
|
||||
|
||||
3. The 'options' argument is the only argument that is a regular 'Object'.
|
||||
|
||||
Other arguments can be objects, but they must be distinguishable from a
|
||||
'plain' Object runtime, by having either:
|
||||
|
||||
- a distinguishing prototype (e.g. `Array`, `Map`, `Date`, `class MyThing`)
|
||||
- a well-known symbol property (e.g. an iterable with `Symbol.iterator`).
|
||||
|
||||
This allows the API to evolve in a backwards compatible way, even when the
|
||||
position of the options object changes.
|
||||
|
||||
```ts
|
||||
// BAD: optional parameters not part of options object. (#2)
|
||||
export function resolve(
|
||||
hostname: string,
|
||||
family?: "ipv4" | "ipv6",
|
||||
timeout?: number
|
||||
): IPAddress[] {}
|
||||
|
||||
// GOOD.
|
||||
export interface ResolveOptions {
|
||||
family?: "ipv4" | "ipv6";
|
||||
timeout?: number;
|
||||
}
|
||||
export function resolve(
|
||||
hostname: string,
|
||||
options: ResolveOptions = {}
|
||||
): IPAddress[] {}
|
||||
```
|
||||
|
||||
```ts
|
||||
export interface Environment {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
// BAD: `env` could be a regular Object and is therefore indistinguishable
|
||||
// from an options object. (#3)
|
||||
export function runShellWithEnv(cmdline: string, env: Environment): string {}
|
||||
|
||||
// GOOD.
|
||||
export interface RunShellOptions {
|
||||
env: Environment;
|
||||
}
|
||||
export function runShellWithEnv(
|
||||
cmdline: string,
|
||||
options: RunShellOptions
|
||||
): string {}
|
||||
```
|
||||
|
||||
```ts
|
||||
// BAD: more than 3 arguments (#1), multiple optional parameters (#2).
|
||||
export function renameSync(
|
||||
oldname: string,
|
||||
newname: string,
|
||||
replaceExisting?: boolean,
|
||||
followLinks?: boolean
|
||||
) {}
|
||||
|
||||
// GOOD.
|
||||
interface RenameOptions {
|
||||
replaceExisting?: boolean;
|
||||
followLinks?: boolean;
|
||||
}
|
||||
export function renameSync(
|
||||
oldname: string,
|
||||
newname: string,
|
||||
options: RenameOptions = {}
|
||||
) {}
|
||||
```
|
||||
|
||||
```ts
|
||||
// BAD: too many arguments. (#1)
|
||||
export function pwrite(
|
||||
fd: number,
|
||||
buffer: TypedArray,
|
||||
offset: number,
|
||||
length: number,
|
||||
position: number
|
||||
) {}
|
||||
|
||||
// BETTER.
|
||||
export interface PWrite {
|
||||
fd: number;
|
||||
buffer: TypedArray;
|
||||
offset: number;
|
||||
length: number;
|
||||
position: number;
|
||||
}
|
||||
export function pwrite(options: PWrite) {}
|
||||
```
|
||||
|
||||
## TODO Comments
|
||||
|
||||
TODO comments should be include an issue or the author's github username in
|
||||
parentheses. Example:
|
||||
|
||||
```
|
||||
// TODO(ry) Add tests.
|
||||
// TODO(#123) Support Windows.
|
||||
```
|
||||
|
||||
## Copyright headers
|
||||
|
||||
Most files in `deno_std` should have the following copyright header:
|
||||
|
||||
```
|
||||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
```
|
||||
|
||||
If the code originates elsewhere, ensure that the file has the proper copyright
|
||||
headers. We only allow MIT, BSD, and Apache licensed code in `deno_std`.
|
||||
|
||||
## Top level functions should not use arrow syntax
|
||||
|
||||
Top level functions should use the `function` keyword. Arrow syntax should be
|
||||
limited to closures.
|
||||
|
||||
Bad
|
||||
|
||||
```
|
||||
export const foo(): string => {
|
||||
return "bar";
|
||||
}
|
||||
```
|
||||
|
||||
Good
|
||||
|
||||
```
|
||||
export function foo(): string {
|
||||
return "bar";
|
||||
}
|
||||
```
|
||||
|
||||
## Meta-programming is discouraged. Including the use of Proxy.
|
||||
|
||||
Be explicit even when it means more code.
|
||||
|
||||
There are some situations where it may make sense to use such techniques, but in
|
||||
the vast majority of cases it does not.
|
||||
|
||||
## If a filename starts with underscore, do not link to it: `_foo.ts`
|
||||
|
||||
Sometimes there maybe situations where an internal module is necessary but its
|
||||
API is not meant to be stable or linked to. In this case prefix it with an
|
||||
underscore. By convention, only files in its own directory should import it.
|
||||
|
||||
## Use JSDoc to document exported machinery
|
||||
|
||||
We strive for complete documentation. Every exported symbol ideally should have
|
||||
a documentation line.
|
||||
|
||||
If possible, use a single line for the JS Doc. Example:
|
||||
|
||||
```ts
|
||||
/** foo does bar. */
|
||||
export function foo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
It is important that documentation is easily human readable, but there is also a
|
||||
need to provide additional styling information to ensure generated documentation
|
||||
is more rich text. Therefore JSDoc should generally follow markdown markup to
|
||||
enrich the text.
|
||||
|
||||
While markdown supports HTML tags, it is forbidden in JSDoc blocks.
|
||||
|
||||
Code string literals should be braced with the back-tick (\`) instead of quotes.
|
||||
For example:
|
||||
|
||||
```ts
|
||||
/** Import something from the `deno` module. */
|
||||
```
|
||||
|
||||
Do not document function arguments unless they are non-obvious of their intent
|
||||
(though if they are non-obvious intent, the API should be considered anyways).
|
||||
Therefore `@param` should generally not be used.
|
||||
|
||||
Vertical spacing should be minimized whenever possible. Therefore single line
|
||||
comments should be written as:
|
||||
|
||||
```ts
|
||||
/** This is a good single line JSDoc */
|
||||
```
|
||||
|
||||
And not
|
||||
|
||||
```ts
|
||||
/**
|
||||
* This is a bad single line JSDoc
|
||||
*/
|
||||
```
|
||||
|
||||
Code examples should not utilise the triple-back tick (\`\`\`) notation or tags.
|
||||
They should just be marked by indentation, which requires a break before the
|
||||
block and 6 additional spaces for each line of the example. This is 4 more than
|
||||
the first column of the comment. For example:
|
||||
|
||||
```ts
|
||||
/** A straight forward comment and an example:
|
||||
*
|
||||
* import { foo } from "deno";
|
||||
* foo("bar");
|
||||
*/
|
||||
```
|
||||
|
||||
Code examples should not contain additional comments. It is already inside a
|
||||
comment. If it needs further comments is not a good example.
|
1
website/welcome.js
Normal file
1
website/welcome.js
Normal file
|
@ -0,0 +1 @@
|
|||
console.log("Welcome to Deno 🦕");
|
Loading…
Reference in a new issue