diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2019-02-11 17:41:13 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-11 17:41:13 -0500 |
commit | a4dec944bc821d114bfd82debb72d60bd04f836d (patch) | |
tree | 5e090d3b19e396baec5dddaa81a6cfa5ff96addb | |
parent | 489c69f8e1c15c75461d24d91aa3e9c2a756e807 (diff) |
web design (#1728)
-rw-r--r-- | .github/CONTRIBUTING.md | 98 | ||||
-rw-r--r-- | .github/PULL_REQUEST_TEMPLATE.md | 2 | ||||
-rw-r--r-- | Docs.md | 440 | ||||
-rw-r--r-- | README.md | 86 | ||||
-rw-r--r-- | Roadmap.md | 61 | ||||
-rwxr-xr-x | tools/format.ts | 2 | ||||
-rw-r--r-- | website/README.md | 32 | ||||
-rw-r--r-- | website/all_benchmark.html | 44 | ||||
-rw-r--r-- | website/app.js | 4 | ||||
-rw-r--r-- | website/benchmarks.html | 137 | ||||
-rw-r--r-- | website/index.html | 220 | ||||
-rw-r--r-- | website/manifest.json | 13 | ||||
-rw-r--r-- | website/manual.html | 40 | ||||
-rw-r--r-- | website/manual.md | 656 | ||||
-rw-r--r-- | website/schematic_v0.2.png | bin | 0 -> 58275 bytes | |||
-rw-r--r-- | website/showdown_toc.js | 142 | ||||
-rw-r--r-- | website/style.css | 95 | ||||
-rw-r--r-- | website/style_guide.html | 40 | ||||
-rw-r--r-- | website/style_guide.md | 264 | ||||
-rw-r--r-- | website/welcome.js | 1 |
20 files changed, 1406 insertions, 971 deletions
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index dac3f372b..000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -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. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 427ca16c9..6b5df6182 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -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 --> @@ -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 @@ -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 diff --git a/Roadmap.md b/Roadmap.md deleted file mode 100644 index 572d03543..000000000 --- a/Roadmap.md +++ /dev/null @@ -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 -% -``` diff --git a/tools/format.ts b/tools/format.ts index 37fbd18e3..8f86ea979 100755 --- a/tools/format.ts +++ b/tools/format.ts @@ -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"], diff --git a/website/README.md b/website/README.md deleted file mode 100644 index 1e6a13a15..000000000 --- a/website/README.md +++ /dev/null @@ -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; - }; -} -``` diff --git a/website/all_benchmark.html b/website/all_benchmark.html deleted file mode 100644 index 1d73d5831..000000000 --- a/website/all_benchmark.html +++ /dev/null @@ -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> - diff --git a/website/app.js b/website/app.js index ed7d4baf2..6e23befa9 100644 --- a/website/app.js +++ b/website/app.js @@ -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"); diff --git a/website/benchmarks.html b/website/benchmarks.html new file mode 100644 index 000000000..0c270d2be --- /dev/null +++ b/website/benchmarks.html @@ -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> diff --git a/website/index.html b/website/index.html index 86463e5d8..ffd83a253 100644 --- a/website/index.html +++ b/website/index.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/ --> - - <h1>Deno</h1> - - <p> - A new way to JavaScript - - <!-- TODO(ry) add the registry badges. --> - </p> + <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> + A new way to JavaScript + </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 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> + <p>Try running a simple program:</p> + <pre>deno https://deno.land/welcome.js</pre> + + <p>Or a more complex one:</p> - <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> +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"); - <h2 id="dig-in"><a href="#dig-in">#</a>Dig in...</h2> +async function main() { + for await (const req of s) { + req.respond({ body: new TextEncoder().encode("Hello World\n") }); + } +} - <a href="https://github.com/denoland/deno/blob/master/Docs.md"> - Documentation - </a> +main(); </pre> - <p> - <a href="typedoc/index.html">API Reference</a> - </p> + <h2 id="dig-in">Dig in... <a href="#dig-in">#</a></h2> <p> - <a href="https://github.com/denolib/awesome-deno"> - Links to other Deno resources. - </a> + <b><a href="manual.html">Manual</a></b> </p> - <h2 id="benchmarks"><a href="#benchmarks">#</a>Continuous Benchmarks</h2> + <p><a href="https://deno.land/typedoc">API Reference</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="style_guide.html">Style Guide</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><a href="https://gitter.im/denolife/Lobby">Community chat room</a></p> - <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><a href="benchmarks.html">Benchmarks</a></p> <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"><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="./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> diff --git a/website/manifest.json b/website/manifest.json deleted file mode 100644 index 67e8f1a0b..000000000 --- a/website/manifest.json +++ /dev/null @@ -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" -} diff --git a/website/manual.html b/website/manual.html new file mode 100644 index 000000000..1301b6895 --- /dev/null +++ b/website/manual.html @@ -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> 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"; +``` diff --git a/website/schematic_v0.2.png b/website/schematic_v0.2.png Binary files differnew file mode 100644 index 000000000..abf7b1f2e --- /dev/null +++ b/website/schematic_v0.2.png diff --git a/website/showdown_toc.js b/website/showdown_toc.js new file mode 100644 index 000000000..ba1f65c71 --- /dev/null +++ b/website/showdown_toc.js @@ -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); + } + }; +}); diff --git a/website/style.css b/website/style.css index 5b44d3799..b16d33eb7 100644 --- a/website/style.css +++ b/website/style.css @@ -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; } -@media only screen and (max-device-width: 480px) { +header h1 { + margin: 8px 0; +} - main { - margin: 15px; - } +@media only screen and (max-device-width: 480px) { body { margin: 0; } diff --git a/website/style_guide.html b/website/style_guide.html new file mode 100644 index 000000000..4acf13649 --- /dev/null +++ b/website/style_guide.html @@ -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> diff --git a/website/style_guide.md b/website/style_guide.md new file mode 100644 index 000000000..d2cbbbf30 --- /dev/null +++ b/website/style_guide.md @@ -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. diff --git a/website/welcome.js b/website/welcome.js new file mode 100644 index 000000000..69f1069f8 --- /dev/null +++ b/website/welcome.js @@ -0,0 +1 @@ +console.log("Welcome to Deno 🦕"); |