From b8612838a034baacd9df27d96c4e4ed4dfbd4a4b Mon Sep 17 00:00:00 2001 From: Jo Franchetti Date: Mon, 2 Sep 2024 18:39:39 +0100 Subject: [PATCH 01/12] moving over reference guide --- data.json | 2 +- examples/benchmarking.ts | 2 +- runtime/_data.ts | 142 +++++++++--------- runtime/fundamentals/configuration.md | 6 +- .../fundamentals/linting_and_formatting.md | 2 +- runtime/fundamentals/stability.md | 2 +- runtime/fundamentals/testing.md | 4 +- runtime/fundamentals/typescript.md | 2 +- .../getting_started/command_line_interface.md | 2 +- runtime/getting_started/first_project.md | 4 +- .../getting_started/setup_your_environment.md | 2 +- runtime/manual/basics/vendoring/index.md | 2 +- .../getting_started/setup_your_environment.md | 8 +- runtime/manual/node/index.md | 4 +- runtime/manual/tools/____template.md | 61 -------- runtime/manual/tools/_category_.json | 8 - runtime/manual/tools/index.md | 41 ----- .../tools => reference/cli}/benchmarker.md | 1 + .../tools => reference/cli}/bundler.md | 1 + .../{manual/tools => reference/cli}/cache.md | 1 + .../{manual/tools => reference/cli}/check.md | 1 + .../tools => reference/cli}/compiler.md | 1 + .../tools => reference/cli}/completions.md | 1 + .../tools => reference/cli}/coverage.md | 1 + .../cli}/dependency_inspector.md | 1 + .../cli}/documentation_generator.md | 1 + .../tools => reference/cli}/env_variables.md | 1 + .../{manual/tools => reference/cli}/eval.md | 1 + .../tools => reference/cli}/formatter.md | 1 + .../{manual/tools => reference/cli}/init.md | 1 + .../tools => reference/cli}/jupyter.md | 2 +- .../{manual/tools => reference/cli}/linter.md | 1 + .../{manual/tools => reference/cli}/lsp.md | 3 +- .../cli}/lsp_integration.md | 1 + .../tools => reference/cli}/publish.md | 1 + .../{manual/tools => reference/cli}/repl.md | 1 + .../{manual/tools => reference/cli}/run.md | 1 + .../cli}/script_installer.md | 1 + .../{manual/tools => reference/cli}/serve.md | 1 + .../tools => reference/cli}/task_runner.md | 1 + .../{manual/tools => reference/cli}/test.md | 1 + .../{manual/tools => reference/cli}/types.md | 1 + .../tools => reference/cli}/uninstall.md | 1 + .../tools => reference/cli}/unstable_flags.md | 1 + .../tools => reference/cli}/upgrade.md | 1 + 45 files changed, 121 insertions(+), 204 deletions(-) delete mode 100644 runtime/manual/tools/____template.md delete mode 100644 runtime/manual/tools/_category_.json delete mode 100644 runtime/manual/tools/index.md rename runtime/{manual/tools => reference/cli}/benchmarker.md (99%) rename runtime/{manual/tools => reference/cli}/bundler.md (97%) rename runtime/{manual/tools => reference/cli}/cache.md (99%) rename runtime/{manual/tools => reference/cli}/check.md (98%) rename runtime/{manual/tools => reference/cli}/compiler.md (98%) rename runtime/{manual/tools => reference/cli}/completions.md (96%) rename runtime/{manual/tools => reference/cli}/coverage.md (98%) rename runtime/{manual/tools => reference/cli}/dependency_inspector.md (99%) rename runtime/{manual/tools => reference/cli}/documentation_generator.md (98%) rename runtime/{manual/tools => reference/cli}/env_variables.md (98%) rename runtime/{manual/tools => reference/cli}/eval.md (99%) rename runtime/{manual/tools => reference/cli}/formatter.md (98%) rename runtime/{manual/tools => reference/cli}/init.md (98%) rename runtime/{manual/tools => reference/cli}/jupyter.md (98%) rename runtime/{manual/tools => reference/cli}/linter.md (98%) rename runtime/{manual/tools => reference/cli}/lsp.md (89%) rename runtime/{manual/tools => reference/cli}/lsp_integration.md (99%) rename runtime/{manual/tools => reference/cli}/publish.md (98%) rename runtime/{manual/tools => reference/cli}/repl.md (99%) rename runtime/{manual/tools => reference/cli}/run.md (98%) rename runtime/{manual/tools => reference/cli}/script_installer.md (98%) rename runtime/{manual/tools => reference/cli}/serve.md (96%) rename runtime/{manual/tools => reference/cli}/task_runner.md (99%) rename runtime/{manual/tools => reference/cli}/test.md (99%) rename runtime/{manual/tools => reference/cli}/types.md (94%) rename runtime/{manual/tools => reference/cli}/uninstall.md (95%) rename runtime/{manual/tools => reference/cli}/unstable_flags.md (99%) rename runtime/{manual/tools => reference/cli}/upgrade.md (97%) diff --git a/data.json b/data.json index 1d16320f1..170221b29 100644 --- a/data.json +++ b/data.json @@ -7,7 +7,7 @@ "category": "Runtime" }, { - "path": "/runtime/manual/tools/test/", + "path": "/runtime/reference/cli/test/", "title": "deno test", "content": "Run tests using Deno's built-in test runner.\n", "section": "deno test", diff --git a/examples/benchmarking.ts b/examples/benchmarking.ts index 37901021d..0e95cf546 100644 --- a/examples/benchmarking.ts +++ b/examples/benchmarking.ts @@ -3,7 +3,7 @@ * @difficulty beginner * @tags cli * @run deno bench - * @resource {https://docs.deno.com/runtime/manual/tools/benchmarker} Manual: Benchmarker tool + * @resource {https://docs.deno.com/runtime/reference/cli/benchmarker} Manual: Benchmarker tool * @resource {/examples/http-requests} Example: HTTP Requests * @group System * diff --git a/runtime/_data.ts b/runtime/_data.ts index 4fcb80d37..36c5c8aef 100644 --- a/runtime/_data.ts +++ b/runtime/_data.ts @@ -34,156 +34,156 @@ export const sidebar = [ ], }, { - title: "Modules and APIs", - items: [ - { - label: "Deno Runtime APIs", - items: [ - "/runtime/manual/runtime/builtin_apis/", - "/runtime/manual/runtime/http_server_apis/", - "/runtime/manual/runtime/permission_apis/", - "/runtime/manual/runtime/import_meta_api/", - "/runtime/manual/runtime/ffi_api/", - "/runtime/manual/runtime/program_lifecycle/", - ], - }, - { - label: "Web Platform APIs", - items: [ - "/runtime/manual/runtime/web_platform_apis/", - "/runtime/manual/runtime/location_api/", - "/runtime/manual/runtime/web_storage_api/", - "/runtime/manual/runtime/workers/", - ], - }, - { - label: "Interop with Node & npm", - items: [ - "/runtime/manual/node/", - "/runtime/manual/node/migrate/", - "/runtime/manual/node/npm_specifiers/", - "/runtime/manual/node/private_registries/", - "/runtime/manual/node/cjs_to_esm/", - "/runtime/manual/node/cheatsheet/", - { - label: "Supported Node APIs and globals", - id: "/runtime/manual/node/compatibility/", - }, - ], - }, - "/runtime/manual/advanced/jsx/", - ], - }, - { - title: "Development Tools", + title: "Reference Guides", items: [ { - label: "CLI Command Reference", + label: "Deno CLI", items: [ - "/runtime/manual/tools/", - "/runtime/manual/tools/unstable_flags/", + "/runtime/reference/cli/unstable_flags/", { label: "deno bench", - id: "/runtime/manual/tools/benchmarker/", + id: "/runtime/reference/cli/benchmarker/", }, { label: "deno completions", - id: "/runtime/manual/tools/completions/", + id: "/runtime/reference/cli/completions/", }, { label: "deno cache", - id: "/runtime/manual/tools/cache/", + id: "/runtime/reference/cli/cache/", }, { label: "deno check", - id: "/runtime/manual/tools/check/", + id: "/runtime/reference/cli/check/", }, { label: "deno compile", - id: "/runtime/manual/tools/compiler/", + id: "/runtime/reference/cli/compiler/", }, { label: "deno coverage", - id: "/runtime/manual/tools/coverage/", + id: "/runtime/reference/cli/coverage/", }, { label: "deno doc", - id: "/runtime/manual/tools/documentation_generator/", + id: "/runtime/reference/cli/documentation_generator/", }, { label: "deno eval", - id: "/runtime/manual/tools/eval/", + id: "/runtime/reference/cli/eval/", }, { label: "deno fmt", - id: "/runtime/manual/tools/formatter/", + id: "/runtime/reference/cli/formatter/", }, { label: "deno info", - id: "/runtime/manual/tools/dependency_inspector/", + id: "/runtime/reference/cli/dependency_inspector/", }, { label: "deno init", - id: "/runtime/manual/tools/init/", + id: "/runtime/reference/cli/init/", }, { label: "deno install", - id: "/runtime/manual/tools/script_installer/", + id: "/runtime/reference/cli/script_installer/", }, { label: "deno jupyter", - id: "/runtime/manual/tools/jupyter/", + id: "/runtime/reference/cli/jupyter/", }, { label: "deno lint", - id: "/runtime/manual/tools/linter/", + id: "/runtime/reference/cli/linter/", }, { label: "deno publish", - id: "/runtime/manual/tools/publish/", + id: "/runtime/reference/cli/publish/", }, { label: "deno lsp", - id: "/runtime/manual/tools/lsp/", + id: "/runtime/reference/cli/lsp/", }, { label: "deno repl", - id: "/runtime/manual/tools/repl/", + id: "/runtime/reference/cli/repl/", }, { label: "deno run", - id: "/runtime/manual/tools/run/", + id: "/runtime/reference/cli/run/", }, { label: "deno serve", - id: "/runtime/manual/tools/serve/", + id: "/runtime/reference/cli/serve/", }, { label: "deno task", - id: "/runtime/manual/tools/task_runner/", + id: "/runtime/reference/cli/task_runner/", }, { label: "deno test", - id: "/runtime/manual/tools/test/", + id: "/runtime/reference/cli/test/", }, { label: "deno types", - id: "/runtime/manual/tools/types/", + id: "/runtime/reference/cli/types/", }, { label: "deno uninstall", - id: "/runtime/manual/tools/uninstall/", + id: "/runtime/reference/cli/uninstall/", }, { label: "deno upgrade", - id: "/runtime/manual/tools/upgrade/", + id: "/runtime/reference/cli/upgrade/", }, ], + } + ], + }, + { + title: "Modules and APIs", + items: [ + { + label: "Deno Runtime APIs", + items: [ + "/runtime/manual/runtime/builtin_apis/", + "/runtime/manual/runtime/http_server_apis/", + "/runtime/manual/runtime/permission_apis/", + "/runtime/manual/runtime/import_meta_api/", + "/runtime/manual/runtime/ffi_api/", + "/runtime/manual/runtime/program_lifecycle/", + ], + }, + { + label: "Web Platform APIs", + items: [ + "/runtime/manual/runtime/web_platform_apis/", + "/runtime/manual/runtime/location_api/", + "/runtime/manual/runtime/web_storage_api/", + "/runtime/manual/runtime/workers/", + ], }, { - label: "Vendoring", - id: "/runtime/manual/basics/vendoring/", + label: "Interop with Node & npm", + items: [ + "/runtime/manual/node/", + "/runtime/manual/node/migrate/", + "/runtime/manual/node/npm_specifiers/", + "/runtime/manual/node/private_registries/", + "/runtime/manual/node/cjs_to_esm/", + "/runtime/manual/node/cheatsheet/", + { + label: "Supported Node APIs and globals", + id: "/runtime/manual/node/compatibility/", + }, + ], }, + "/runtime/manual/advanced/jsx/", + ], + }, + { + title: "Development Tools", + items: [ { label: "Visual Studio Code", items: [ diff --git a/runtime/fundamentals/configuration.md b/runtime/fundamentals/configuration.md index 380b8eb50..9348522ed 100644 --- a/runtime/fundamentals/configuration.md +++ b/runtime/fundamentals/configuration.md @@ -103,7 +103,7 @@ deno task test deno task lint ``` -Read more about [`deno task`](/runtime/manual/tools/task_runner/). +Read more about [`deno task`](/runtime/reference/cli/task_runner/). ## Linting @@ -140,7 +140,7 @@ This configuration will: You can find a full list of available linting rules in the [Deno lint documentation](https://lint.deno.land/). -Read more about [linting with Deno](/runtime/manual/tools/linter/). +Read more about [linting with Deno](/runtime/reference/cli/linter/). ## Formatting @@ -229,7 +229,7 @@ The `unstable` field in a `deno.json` file is used to enable specific unstable feature flags for your Deno project. These features are still in development and not yet part of the stable API. By listing the desired features in the unstable array, you can experiment with and use these new capabilities before they are -officially released. [Learn more](/runtime/manual/tools/unstable_flags/). +officially released. [Learn more](/runtime/reference/cli/unstable_flags/). ## include and exclude diff --git a/runtime/fundamentals/linting_and_formatting.md b/runtime/fundamentals/linting_and_formatting.md index f328a5c3f..21fa2b329 100644 --- a/runtime/fundamentals/linting_and_formatting.md +++ b/runtime/fundamentals/linting_and_formatting.md @@ -18,7 +18,7 @@ building amazing applications. Linting is the process of analyzing your code for potential errors, bugs, and stylistic issues. Deno’s built-in linter, -[`deno lint`](/runtime/manual/tools/linter/), supports recommended set of rules +[`deno lint`](/runtime/reference/cli/linter/), supports recommended set of rules from [ESLint](https://eslint.org/) to provide comprehensive feedback on your code. This includes identifying syntax errors, enforcing coding conventions, and highlighting potential issues that could lead to bugs. diff --git a/runtime/fundamentals/stability.md b/runtime/fundamentals/stability.md index c698164db..0a2dda094 100644 --- a/runtime/fundamentals/stability.md +++ b/runtime/fundamentals/stability.md @@ -9,7 +9,7 @@ strive to make code working under 1.0.0 continue to work in future versions. When introducing new APIs, these are first marked as unstable. This means that the API may change in the future. These APIs are not available to use unless you explicitly pass an unstable flag, like `--unstable-kv`. -[Learn more about `--unstable-*` flags](/runtime/manual/tools/unstable_flags). +[Learn more about `--unstable-*` flags](/runtime/reference/cli/unstable_flags). There are also some non-runtime features of Deno that are considered unstable, and are locked behind unstable flags. For example, the diff --git a/runtime/fundamentals/testing.md b/runtime/fundamentals/testing.md index e50aeda5c..9326948a2 100644 --- a/runtime/fundamentals/testing.md +++ b/runtime/fundamentals/testing.md @@ -75,7 +75,7 @@ Deno.test("add function adds two numbers correctly", () => { ## Running Tests -To run your tests, use the [`deno test`](/runtime/manual/tools/test/) +To run your tests, use the [`deno test`](/runtime/reference/cli/test/) subcommand. If run without a file name or directory name, this subcommand will automatically @@ -293,7 +293,7 @@ the `--coverage` flag when starting `deno test`. This coverage information is acquired directly from the V8 JavaScript engine, ensuring high accuracy. This can then be further processed from the internal format into well known -formats with the [`deno coverage`](/runtime/manual/tools/coverage/) tool. +formats with the [`deno coverage`](/runtime/reference/cli/coverage/) tool. ## Behavior-Driven Development diff --git a/runtime/fundamentals/typescript.md b/runtime/fundamentals/typescript.md index 3dc04de31..509c62e40 100644 --- a/runtime/fundamentals/typescript.md +++ b/runtime/fundamentals/typescript.md @@ -33,7 +33,7 @@ team ::: Deno allows you to type-check your code (without executing it) with the -[`deno check`](/runtime/manual/tools/check/) subcommand: +[`deno check`](/runtime/reference/cli/check/) subcommand: ```shell deno check module.ts diff --git a/runtime/getting_started/command_line_interface.md b/runtime/getting_started/command_line_interface.md index a3b0f312f..64a5dc038 100644 --- a/runtime/getting_started/command_line_interface.md +++ b/runtime/getting_started/command_line_interface.md @@ -20,7 +20,7 @@ used to customize its behavior. You can view all of the available commands and flags by running the `deno help` subcommand in your terminal, or using the `-h` or `--help` flags. -Check out the [CLI reference guide](/runtime/manual/tools/) for a further +Check out the [CLI reference guide](/runtime/reference/cli/) for a further documentation on all the subcommands and flags available. We'll take a look at a few commands in a bit more detail below to see how they can be used and configured. diff --git a/runtime/getting_started/first_project.md b/runtime/getting_started/first_project.md index 500c9ca5d..c7406edc3 100644 --- a/runtime/getting_started/first_project.md +++ b/runtime/getting_started/first_project.md @@ -3,9 +3,9 @@ title: Making a Deno project oldUrl: /runtime/manual/getting_started/first_steps/ --- -Deno has many [built in tools](/runtime/manual/tools/) to make your development +Deno has many [built in tools](/runtime/reference/cli/) to make your development experience as smooth as possible. One of these tools is the -[project initializer](/runtime/manual/tools/init/), which creates a new Deno +[project initializer](/runtime/reference/cli/init/), which creates a new Deno project with a basic file structure and configuration. While you are welcome to use JavaScript, Deno has built-in support for diff --git a/runtime/getting_started/setup_your_environment.md b/runtime/getting_started/setup_your_environment.md index c46a909c5..c956bc165 100644 --- a/runtime/getting_started/setup_your_environment.md +++ b/runtime/getting_started/setup_your_environment.md @@ -5,7 +5,7 @@ oldUrl: /runtime/manual/getting_started/setup_your_environment/ Deno comes with many of the tools that are commonly needed for developing applications, including a full -[language server (LSP)](/runtime/manual/tools/lsp/) to help power your IDE of +[language server (LSP)](/runtime/reference/cli/lsp/) to help power your IDE of choice. This page will help you set up your environment to get the most out of Deno while you are developing. diff --git a/runtime/manual/basics/vendoring/index.md b/runtime/manual/basics/vendoring/index.md index eb1bdd496..097ada656 100644 --- a/runtime/manual/basics/vendoring/index.md +++ b/runtime/manual/basics/vendoring/index.md @@ -1,7 +1,7 @@ --- title: "Caching dependencies locally (Vendoring)" oldUrl: - - /runtime/manual/tools/vendor + - /runtime/reference/cli/vendor --- If your project has external dependencies, you may want to store them locally to diff --git a/runtime/manual/getting_started/setup_your_environment.md b/runtime/manual/getting_started/setup_your_environment.md index 0ac9adff2..1ce709d43 100644 --- a/runtime/manual/getting_started/setup_your_environment.md +++ b/runtime/manual/getting_started/setup_your_environment.md @@ -414,7 +414,7 @@ There are several environment variables which can impact the behavior of Deno: specific certificate per TLS connection. - `DENO_CERT` - load a certificate authority from a PEM encoded file. This "overrides" the `--cert` option. See the - [Proxies](/runtime/manual/tools/env_variables#proxies) section for more + [Proxies](/runtime/reference/cli/env_variables#proxies) section for more information. - `DENO_DIR` - this will set the directory where cached information from the CLI is stored. This includes items like cached remote modules, cached transpiled @@ -430,10 +430,10 @@ There are several environment variables which can impact the behavior of Deno: available. - `DENO_WEBGPU_TRACE` - The directory to use for WebGPU traces. - `HTTP_PROXY` - The proxy address to use for HTTP requests. See the - [Proxies](/runtime/manual/tools/env_variables#proxies) section for more + [Proxies](/runtime/reference/cli/env_variables#proxies) section for more information. - `HTTPS_PROXY` - The proxy address to use for HTTPS requests. See the - [Proxies](/runtime/manual/tools/env_variables#proxies) section for more + [Proxies](/runtime/reference/cli/env_variables#proxies) section for more information. - `NO_COLOR` - If set, this will prevent the Deno CLI from sending ANSI color codes when writing to stdout and stderr. See the website @@ -443,7 +443,7 @@ There are several environment variables which can impact the behavior of Deno: `Deno.noColor`. - `NO_PROXY` - Indicates hosts which should bypass the proxy set in the other environment variables. See the - [Proxies](/runtime/manual/tools/env_variables#proxies) section for more + [Proxies](/runtime/reference/cli/env_variables#proxies) section for more information. - `NPM_CONFIG_REGISTRY` - The npm registry to use when loading modules via [npm specifiers](../node/npm_specifiers.md) diff --git a/runtime/manual/node/index.md b/runtime/manual/node/index.md index 2cfd3495d..0fb0c7d57 100644 --- a/runtime/manual/node/index.md +++ b/runtime/manual/node/index.md @@ -19,6 +19,6 @@ Node.js projects to Deno. Node and npm compatibility is an ongoing project for the Deno team. As such, there are a number of unstable features aimed at improving compatibility that you may want to reference. Please check out the -[unstable feature flags](/runtime/manual/tools/unstable_flags) documentation for -options that may improve your project's compatibility with code written for +[unstable feature flags](/runtime/reference/cli/unstable_flags) documentation +for options that may improve your project's compatibility with code written for Node.js. diff --git a/runtime/manual/tools/____template.md b/runtime/manual/tools/____template.md deleted file mode 100644 index bab99e612..000000000 --- a/runtime/manual/tools/____template.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "deno foo" ---- - -_This applies to `deno` v.1.17.0. and above._ **Unstable preview feature** - -Do a fooer on a bar. - -## Command - -`deno foo [OPTIONS] ` - Foos a bar. - -## Synopsis - -```bash -deno foo [--token ] [-c|--config ] [-q|--quiet] -[--no-config] [--dry-run] [--allow-slow-types] [--allow-dirty] -[--no-provenance] [--check[=]] [--no-check[=]] - -deno foo -h|--help -``` - -## Description - -This command does a thing. We refer to it by using `deno foo`. - -This is a human written text about the command. - -## Something important - -There might be something important to add. - -## Arguments - -`PROJECT | SOLUTION` - -This is a description of the required arguments - -## Options - -- `-h, --help` - - Prints help information - -- `-s, --something` - - Does a something - -## Examples - -- Run the command - -```bash -deno foo -``` - -- Run the command 2 - -```bash -deno foo2 -``` diff --git a/runtime/manual/tools/_category_.json b/runtime/manual/tools/_category_.json deleted file mode 100644 index e2df477d7..000000000 --- a/runtime/manual/tools/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Built-in Tooling", - "position": 7, - "link": { - "type": "doc", - "id": "index" - } -} diff --git a/runtime/manual/tools/index.md b/runtime/manual/tools/index.md deleted file mode 100644 index 8195533bc..000000000 --- a/runtime/manual/tools/index.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "CLI Command Reference" -oldUrl: /manual/tools ---- - -The Deno CLI provides a number of helpful utilities in addition to running Deno -programs. These tools are listed below. You may also want to check out our list -of [unstable feature flags](./unstable_flags.md), which give early access to new -Deno features before they are finalized. - -- [`deno add`](../basics/modules/index.md#package-registries) - add dependencies -- [`deno bench`](./benchmarker.md) - run benchmarks -- [`deno bundle`](./bundler.md) - bundle module and dependencies into a single - file -- [`deno cache`](./cache.md) - cache dependencies -- [`deno check`](./check.md) - type-check dependencies -- [`deno compile`](./compiler.md) - compile the script into a self contained - executable -- [`deno completions`](./completions.md) - generate shell completions -- [`deno coverage`](./coverage.md) - print coverage reports -- [`deno doc`](./documentation_generator.md) - show documentation for a module -- [`deno eval`](./eval.md) - eval script -- [`deno fmt`](./formatter.md) - format source files -- [`deno help`](./index.md) - show command help text -- [`deno info`](./dependency_inspector.md) - show info about cache or related - source file -- [`deno init`](./init.md) - initialize a new project. -- [`deno install`](./script_installer.md) - install script as an executable -- [`deno jupyter`](./jupyter.md)- Deno kernel for Jupyter notebooks -- [`deno lint`](./linter.md) - lint source files -- [`deno lsp`](./lsp.md) - start the language server -- [`deno publish`](./publish.md) - publish a module to JSR -- [`deno repl`](./repl.md) - read eval print loop -- [`deno run`](./run.md) - run a JavaScript or TypeScript program -- [`deno serve`](./serve.md) - run a server -- [`deno task`](./task_runner.md) - run a task defined in the configuration file -- [`deno test`](../basics/testing/index.md) - run tests -- [`deno types`](./types.md) - print runtime TypeScript declarations -- [`deno uninstall`](./uninstall.md) - uninstall a script previously installed - with deno install -- [`deno upgrade`](./upgrade.md) - upgrade deno executable to given version diff --git a/runtime/manual/tools/benchmarker.md b/runtime/reference/cli/benchmarker.md similarity index 99% rename from runtime/manual/tools/benchmarker.md rename to runtime/reference/cli/benchmarker.md index 0541c1ed3..c575230e3 100644 --- a/runtime/manual/tools/benchmarker.md +++ b/runtime/reference/cli/benchmarker.md @@ -1,5 +1,6 @@ --- title: "`deno bench`, benchmarking tool" +oldUrl: /runtime/reference/cli/benchmarker/ --- Deno has a built-in benchmark runner that you can use for checking performance diff --git a/runtime/manual/tools/bundler.md b/runtime/reference/cli/bundler.md similarity index 97% rename from runtime/manual/tools/bundler.md rename to runtime/reference/cli/bundler.md index 7259a1938..43ee4da2d 100644 --- a/runtime/manual/tools/bundler.md +++ b/runtime/reference/cli/bundler.md @@ -1,5 +1,6 @@ --- title: "Bundler (deprecated)" +oldUrl: /runtime/reference/cli/bundler/ --- :::caution diff --git a/runtime/manual/tools/cache.md b/runtime/reference/cli/cache.md similarity index 99% rename from runtime/manual/tools/cache.md rename to runtime/reference/cli/cache.md index 78704d3ec..1fa760f26 100644 --- a/runtime/manual/tools/cache.md +++ b/runtime/reference/cli/cache.md @@ -1,5 +1,6 @@ --- title: "deno cache" +oldUrl: /runtime/reference/cli/cache/ --- Cache and compile remote dependencies recursively. diff --git a/runtime/manual/tools/check.md b/runtime/reference/cli/check.md similarity index 98% rename from runtime/manual/tools/check.md rename to runtime/reference/cli/check.md index 384b08c8e..3b9c6fe67 100644 --- a/runtime/manual/tools/check.md +++ b/runtime/reference/cli/check.md @@ -1,5 +1,6 @@ --- title: "deno check" +oldUrl: /runtime/reference/cli/check/ --- Type-check a program without execution. diff --git a/runtime/manual/tools/compiler.md b/runtime/reference/cli/compiler.md similarity index 98% rename from runtime/manual/tools/compiler.md rename to runtime/reference/cli/compiler.md index 33b292ff1..ed9b75244 100644 --- a/runtime/manual/tools/compiler.md +++ b/runtime/reference/cli/compiler.md @@ -1,5 +1,6 @@ --- title: "`deno compile`, standalone executables" +oldUrl: /runtime/reference/cli/compiler/ --- `deno compile [--output ] ` will compile the script into a diff --git a/runtime/manual/tools/completions.md b/runtime/reference/cli/completions.md similarity index 96% rename from runtime/manual/tools/completions.md rename to runtime/reference/cli/completions.md index 683e49cc0..1e4bfbef0 100644 --- a/runtime/manual/tools/completions.md +++ b/runtime/reference/cli/completions.md @@ -1,5 +1,6 @@ --- title: "deno completions" +oldUrl: /runtime/reference/cli/completions/ --- Output shell completion script to standard output. diff --git a/runtime/manual/tools/coverage.md b/runtime/reference/cli/coverage.md similarity index 98% rename from runtime/manual/tools/coverage.md rename to runtime/reference/cli/coverage.md index fa99acb19..40e4691bd 100644 --- a/runtime/manual/tools/coverage.md +++ b/runtime/reference/cli/coverage.md @@ -1,5 +1,6 @@ --- title: "deno coverage" +oldUrl: /runtime/reference/cli/coverage/ --- Print coverage reports from coverage profiles. diff --git a/runtime/manual/tools/dependency_inspector.md b/runtime/reference/cli/dependency_inspector.md similarity index 99% rename from runtime/manual/tools/dependency_inspector.md rename to runtime/reference/cli/dependency_inspector.md index ad00e0838..eabde9833 100644 --- a/runtime/manual/tools/dependency_inspector.md +++ b/runtime/reference/cli/dependency_inspector.md @@ -1,5 +1,6 @@ --- title: "`deno info`, dependency inspector" +oldUrl: /runtime/reference/cli/dependency_inspector/ --- `deno info [URL]` will inspect an ES module and all of its dependencies. diff --git a/runtime/manual/tools/documentation_generator.md b/runtime/reference/cli/documentation_generator.md similarity index 98% rename from runtime/manual/tools/documentation_generator.md rename to runtime/reference/cli/documentation_generator.md index c577c1c89..cf5958ad5 100644 --- a/runtime/manual/tools/documentation_generator.md +++ b/runtime/reference/cli/documentation_generator.md @@ -1,5 +1,6 @@ --- title: "`deno doc`, documentation generator" +oldUrl: /runtime/reference/cli/documentation_generator/ --- `deno doc` followed by a list of one or more source files will print the JSDoc diff --git a/runtime/manual/tools/env_variables.md b/runtime/reference/cli/env_variables.md similarity index 98% rename from runtime/manual/tools/env_variables.md rename to runtime/reference/cli/env_variables.md index bbc9c7501..4db4551ae 100644 --- a/runtime/manual/tools/env_variables.md +++ b/runtime/reference/cli/env_variables.md @@ -1,5 +1,6 @@ --- title: "Configuring Deno behavior" +oldUrl: /runtime/reference/cli/env_variables/ --- There are several environment variables which can impact the behavior of Deno: diff --git a/runtime/manual/tools/eval.md b/runtime/reference/cli/eval.md similarity index 99% rename from runtime/manual/tools/eval.md rename to runtime/reference/cli/eval.md index 83d67f61e..1e0049e5d 100644 --- a/runtime/manual/tools/eval.md +++ b/runtime/reference/cli/eval.md @@ -1,5 +1,6 @@ --- title: "deno eval" +oldUrl: /runtime/reference/cli/eval/ --- Evaluate JavaScript from the command line. diff --git a/runtime/manual/tools/formatter.md b/runtime/reference/cli/formatter.md similarity index 98% rename from runtime/manual/tools/formatter.md rename to runtime/reference/cli/formatter.md index 9d9af83b1..b34be0f1d 100644 --- a/runtime/manual/tools/formatter.md +++ b/runtime/reference/cli/formatter.md @@ -2,6 +2,7 @@ title: "`deno fmt`, code formatting" oldUrl: - /runtime/tools/formatter/ + - /runtime/reference/cli/formatter/ --- Deno ships with a built-in code formatter that will auto-format the following diff --git a/runtime/manual/tools/init.md b/runtime/reference/cli/init.md similarity index 98% rename from runtime/manual/tools/init.md rename to runtime/reference/cli/init.md index 19aebc9f2..cf1999605 100644 --- a/runtime/manual/tools/init.md +++ b/runtime/reference/cli/init.md @@ -1,5 +1,6 @@ --- title: "`deno init`, start a new project" +oldUrl: /runtime/reference/cli/init/ --- Starting a new project with Deno has always been incredibly simple: you just diff --git a/runtime/manual/tools/jupyter.md b/runtime/reference/cli/jupyter.md similarity index 98% rename from runtime/manual/tools/jupyter.md rename to runtime/reference/cli/jupyter.md index 64b90002d..cbd5d49d6 100644 --- a/runtime/manual/tools/jupyter.md +++ b/runtime/reference/cli/jupyter.md @@ -1,6 +1,6 @@ --- title: "Jupyter Kernel for Deno" -available_since: 1.37.0 +oldUrl: /runtime/reference/cli/jupyter/ --- Deno ships with a built-in Jupyter kernel that allows you to write JavaScript diff --git a/runtime/manual/tools/linter.md b/runtime/reference/cli/linter.md similarity index 98% rename from runtime/manual/tools/linter.md rename to runtime/reference/cli/linter.md index 657d2a14f..a9cd801b3 100644 --- a/runtime/manual/tools/linter.md +++ b/runtime/reference/cli/linter.md @@ -3,6 +3,7 @@ title: "`deno lint`, linter" oldUrl: - /runtime/tools/linter/ - /runtime/fundamentals/linting_and_formatting/lint-cli-ref + - /runtime/reference/cli/linter/ --- Deno ships with a built-in code linter for JavaScript and TypeScript. diff --git a/runtime/manual/tools/lsp.md b/runtime/reference/cli/lsp.md similarity index 89% rename from runtime/manual/tools/lsp.md rename to runtime/reference/cli/lsp.md index 180a0a36b..fbdcff9ee 100644 --- a/runtime/manual/tools/lsp.md +++ b/runtime/reference/cli/lsp.md @@ -1,5 +1,6 @@ --- title: "deno lsp" +oldUrl: /runtime/reference/cli/lsp/ --- :::info @@ -11,7 +12,7 @@ IDEs with go-to-definition support and automatic code formatting. Starts the Deno language server. The language server is used by editors to provide features like intellisense, code formatting, and more. Read more about -[integrating with the Deno LSP](/runtime/manual/tools/lsp_integration/) +[integrating with the Deno LSP](/runtime/reference/cli/lsp_integration/) ## Command diff --git a/runtime/manual/tools/lsp_integration.md b/runtime/reference/cli/lsp_integration.md similarity index 99% rename from runtime/manual/tools/lsp_integration.md rename to runtime/reference/cli/lsp_integration.md index d1456ff65..1d46063d8 100644 --- a/runtime/manual/tools/lsp_integration.md +++ b/runtime/reference/cli/lsp_integration.md @@ -1,5 +1,6 @@ --- title: "Language Server Protocol Integration" +oldUrl: /runtime/reference/cli/lsp_integration/ --- ## The testing API diff --git a/runtime/manual/tools/publish.md b/runtime/reference/cli/publish.md similarity index 98% rename from runtime/manual/tools/publish.md rename to runtime/reference/cli/publish.md index 5b202c72b..39dac21f8 100644 --- a/runtime/manual/tools/publish.md +++ b/runtime/reference/cli/publish.md @@ -1,5 +1,6 @@ --- title: "deno publish" +oldUrl: /runtime/reference/cli/publish/ --- _This applies to `deno` v1.42.0. and above._ diff --git a/runtime/manual/tools/repl.md b/runtime/reference/cli/repl.md similarity index 99% rename from runtime/manual/tools/repl.md rename to runtime/reference/cli/repl.md index f5bd8c006..ca35d9fdb 100644 --- a/runtime/manual/tools/repl.md +++ b/runtime/reference/cli/repl.md @@ -1,5 +1,6 @@ --- title: "`deno repl`, interactive scripting prompt" +oldUrl: /runtime/reference/cli/repl/ --- `deno repl` starts a read-eval-print-loop, which lets you interactively build up diff --git a/runtime/manual/tools/run.md b/runtime/reference/cli/run.md similarity index 98% rename from runtime/manual/tools/run.md rename to runtime/reference/cli/run.md index 60a929648..450cb38bf 100644 --- a/runtime/manual/tools/run.md +++ b/runtime/reference/cli/run.md @@ -1,5 +1,6 @@ --- title: "`deno run`, run a file" +oldUrl: /runtime/reference/cli/run/ --- `deno run [OPTIONS] [SCRIPT_ARG]` run a JavaScript or TypeScript file. diff --git a/runtime/manual/tools/script_installer.md b/runtime/reference/cli/script_installer.md similarity index 98% rename from runtime/manual/tools/script_installer.md rename to runtime/reference/cli/script_installer.md index f036ffc9c..33c963b47 100644 --- a/runtime/manual/tools/script_installer.md +++ b/runtime/reference/cli/script_installer.md @@ -1,5 +1,6 @@ --- title: "`deno install`, script installer" +oldUrl: /runtime/reference/cli/script_installer/ --- diff --git a/runtime/manual/tools/serve.md b/runtime/reference/cli/serve.md similarity index 96% rename from runtime/manual/tools/serve.md rename to runtime/reference/cli/serve.md index b853b79b4..a91ccb13d 100644 --- a/runtime/manual/tools/serve.md +++ b/runtime/reference/cli/serve.md @@ -1,5 +1,6 @@ --- title: "deno serve" +oldUrl: /runtime/reference/cli/serve/ --- In addition to `deno run`, Deno offers a `deno serve` command-line option that diff --git a/runtime/manual/tools/task_runner.md b/runtime/reference/cli/task_runner.md similarity index 99% rename from runtime/manual/tools/task_runner.md rename to runtime/reference/cli/task_runner.md index a74aea639..3efdcd1cd 100644 --- a/runtime/manual/tools/task_runner.md +++ b/runtime/reference/cli/task_runner.md @@ -2,6 +2,7 @@ title: "`deno task`" oldUrl: - /runtime/tools/task_runner/ + - /runtime/reference/cli/task_runner/ --- `deno task` provides a cross-platform way to define and execute custom commands diff --git a/runtime/manual/tools/test.md b/runtime/reference/cli/test.md similarity index 99% rename from runtime/manual/tools/test.md rename to runtime/reference/cli/test.md index c50f13706..6b159bd3a 100644 --- a/runtime/manual/tools/test.md +++ b/runtime/reference/cli/test.md @@ -1,5 +1,6 @@ --- title: "deno test" +oldUrl: /runtime/reference/cli/test/ --- Run tests using Deno's built-in test runner. diff --git a/runtime/manual/tools/types.md b/runtime/reference/cli/types.md similarity index 94% rename from runtime/manual/tools/types.md rename to runtime/reference/cli/types.md index 7ddcc5351..effc7734d 100644 --- a/runtime/manual/tools/types.md +++ b/runtime/reference/cli/types.md @@ -1,5 +1,6 @@ --- title: "deno types" +oldUrl: /runtime/reference/cli/types/ --- Prints runtime TypeScript declarations. diff --git a/runtime/manual/tools/uninstall.md b/runtime/reference/cli/uninstall.md similarity index 95% rename from runtime/manual/tools/uninstall.md rename to runtime/reference/cli/uninstall.md index 5d2a8faf5..eeb471a9c 100644 --- a/runtime/manual/tools/uninstall.md +++ b/runtime/reference/cli/uninstall.md @@ -1,5 +1,6 @@ --- title: "deno uninstall" +oldUrl: /runtime/reference/cli/uninstall/ --- Uninstalls an executable script in the installation root's bin directory. diff --git a/runtime/manual/tools/unstable_flags.md b/runtime/reference/cli/unstable_flags.md similarity index 99% rename from runtime/manual/tools/unstable_flags.md rename to runtime/reference/cli/unstable_flags.md index 6fc9c6624..3b4671c02 100644 --- a/runtime/manual/tools/unstable_flags.md +++ b/runtime/reference/cli/unstable_flags.md @@ -2,6 +2,7 @@ title: "Unstable Feature Flags" oldUrl: - /runtime/tools/unstable_flags/ + - /runtime/reference/cli/unstable_flags/ --- New features of the Deno runtime are often released behind feature flags, so diff --git a/runtime/manual/tools/upgrade.md b/runtime/reference/cli/upgrade.md similarity index 97% rename from runtime/manual/tools/upgrade.md rename to runtime/reference/cli/upgrade.md index c130da4b6..d8fe1a9f0 100644 --- a/runtime/manual/tools/upgrade.md +++ b/runtime/reference/cli/upgrade.md @@ -1,5 +1,6 @@ --- title: "deno upgrade" +oldUrl: /runtime/reference/cli/upgrade/ --- Upgrade deno executable to the given version. From 7a9f52517feb6138bd6468b4722bb6f27602c729 Mon Sep 17 00:00:00 2001 From: Jo Franchetti Date: Mon, 2 Sep 2024 22:22:15 +0100 Subject: [PATCH 02/12] moving over web apis, platform apis and wasm --- runtime/_data.ts | 39 +- .../http_server.md} | 133 ++- runtime/manual/help.md | 1 + runtime/manual/runtime/builtin_apis.md | 74 -- runtime/manual/runtime/ffi_api.md | 292 ------ runtime/manual/runtime/import_meta_api.md | 139 --- runtime/manual/runtime/index.md | 34 - runtime/manual/runtime/location_api.md | 78 -- runtime/manual/runtime/permission_apis.md | 213 ---- runtime/manual/runtime/program_lifecycle.md | 212 ---- runtime/manual/runtime/web_platform_apis.md | 176 ---- runtime/manual/runtime/web_storage_api.md | 59 -- runtime/manual/runtime/webassembly/index.md | 17 - .../webassembly/using_streaming_wasm.md | 42 - .../manual/runtime/webassembly/using_wasm.md | 55 - .../runtime/webassembly/wasm_resources.md | 43 - runtime/manual/runtime/workers.md | 266 ----- runtime/reference/cli/run.md | 6 +- runtime/reference/cli/unstable_flags.md | 2 +- runtime/reference/deno_namespace_apis.md | 947 ++++++++++++++++++ runtime/reference/wasm.md | 136 +++ runtime/reference/web_platform_apis.md | 499 +++++++++ 22 files changed, 1659 insertions(+), 1804 deletions(-) rename runtime/{manual/runtime/http_server_apis.md => fundamentals/http_server.md} (80%) delete mode 100644 runtime/manual/runtime/builtin_apis.md delete mode 100644 runtime/manual/runtime/ffi_api.md delete mode 100644 runtime/manual/runtime/import_meta_api.md delete mode 100644 runtime/manual/runtime/index.md delete mode 100644 runtime/manual/runtime/location_api.md delete mode 100644 runtime/manual/runtime/permission_apis.md delete mode 100644 runtime/manual/runtime/program_lifecycle.md delete mode 100644 runtime/manual/runtime/web_platform_apis.md delete mode 100644 runtime/manual/runtime/web_storage_api.md delete mode 100644 runtime/manual/runtime/webassembly/index.md delete mode 100644 runtime/manual/runtime/webassembly/using_streaming_wasm.md delete mode 100644 runtime/manual/runtime/webassembly/using_wasm.md delete mode 100644 runtime/manual/runtime/webassembly/wasm_resources.md delete mode 100644 runtime/manual/runtime/workers.md create mode 100644 runtime/reference/deno_namespace_apis.md create mode 100644 runtime/reference/wasm.md create mode 100644 runtime/reference/web_platform_apis.md diff --git a/runtime/_data.ts b/runtime/_data.ts index 36c5c8aef..8a0ef3a43 100644 --- a/runtime/_data.ts +++ b/runtime/_data.ts @@ -28,8 +28,9 @@ export const sidebar = [ "/runtime/fundamentals/testing/", "/runtime/fundamentals/debugging/", "/runtime/fundamentals/workspaces/", - "/runtime/fundamentals/installation/", "/runtime/fundamentals/linting_and_formatting/", + "/runtime/fundamentals/http_server/", + "/runtime/fundamentals/installation/", "/runtime/fundamentals/stability/", ], }, @@ -137,32 +138,15 @@ export const sidebar = [ id: "/runtime/reference/cli/upgrade/", }, ], - } + }, + "/runtime/reference/deno_namespace_apis/", + "/runtime/reference/web_platform_apis/", + "/runtime/reference/wasm/", ], }, { title: "Modules and APIs", items: [ - { - label: "Deno Runtime APIs", - items: [ - "/runtime/manual/runtime/builtin_apis/", - "/runtime/manual/runtime/http_server_apis/", - "/runtime/manual/runtime/permission_apis/", - "/runtime/manual/runtime/import_meta_api/", - "/runtime/manual/runtime/ffi_api/", - "/runtime/manual/runtime/program_lifecycle/", - ], - }, - { - label: "Web Platform APIs", - items: [ - "/runtime/manual/runtime/web_platform_apis/", - "/runtime/manual/runtime/location_api/", - "/runtime/manual/runtime/web_storage_api/", - "/runtime/manual/runtime/workers/", - ], - }, { label: "Interop with Node & npm", items: [ @@ -183,7 +167,7 @@ export const sidebar = [ }, { title: "Development Tools", - items: [ + items: [ { label: "Visual Studio Code", items: [ @@ -226,15 +210,6 @@ export const sidebar = [ "/runtime/manual/advanced/typescript/faqs/", ], }, - { - label: "WebAssembly", - items: [ - "/runtime/manual/runtime/webassembly/", - "/runtime/manual/runtime/webassembly/using_wasm/", - "/runtime/manual/runtime/webassembly/using_streaming_wasm/", - "/runtime/manual/runtime/webassembly/wasm_resources/", - ], - }, "/runtime/manual/advanced/migrate_deprecations/", ], }, diff --git a/runtime/manual/runtime/http_server_apis.md b/runtime/fundamentals/http_server.md similarity index 80% rename from runtime/manual/runtime/http_server_apis.md rename to runtime/fundamentals/http_server.md index 514243f89..b55eef132 100644 --- a/runtime/manual/runtime/http_server_apis.md +++ b/runtime/fundamentals/http_server.md @@ -1,22 +1,14 @@ --- -title: "HTTP Server APIs" +title: "Writing an HTTP Server" +oldUrl: + - /runtime/manual/runtime/http_server_apis/ --- -Deno currently has two HTTP Server APIs: +Deno has a built in HTTP server API that allows you to write HTTP servers. The +[`Deno.serve`](https://docs.deno.com/api/deno/~/Deno.serve) API supports +HTTP/1.1 and HTTP2. -- [`Deno.serve`](https://docs.deno.com/api/deno/~/Deno.serve): native, - _higher-level_, supports HTTP/1.1 and HTTP2, this is the preferred API to - write HTTP servers in Deno. -- [`Deno.serveHttp`](https://docs.deno.com/api/deno/~/Deno.serveHttp): native, - _low-level_, supports HTTP/1.1 and HTTP2. -- [A "Hello World" server](#a-hello-world-server) -- [Inspecting the incoming request](#inspecting-the-incoming-request) -- [Responding with a response](#responding-with-a-response) -- [HTTPS support](#https-support) -- [HTTP/2 support](#http2-support) -- [Serving WebSockets](#serving-websockets) - -### A "Hello World" server +## A "Hello World" server To start a HTTP server on a given port, you can use the `Deno.serve` function. This function takes a handler function that will be called for each incoming @@ -32,8 +24,8 @@ Deno.serve((_req) => { }); ``` -> ℹ️ The handler can also return a `Promise`, which means it can be an -> `async` function. +The handler can also return a `Promise`, which means it can be an +`async` function. By default `Deno.serve` will listen on port `8000`, but this can be changed by passing in a port number in options bag as the first or second argument: @@ -46,7 +38,7 @@ Deno.serve({ port: 4242 }, handler); Deno.serve({ port: 4242, hostname: "0.0.0.0", handler }); ``` -### Inspecting the incoming request +## Inspecting the incoming request Most servers will not answer with the same response for every request. Instead they will change their answer depending on various aspects of the request: the @@ -80,7 +72,7 @@ Deno.serve(async (req) => { > as `req.json()`, `req.formData()`, `req.arrayBuffer()`, > `req.body.getReader().read()`, `req.body.pipeTo()`, etc. -### Responding with a response +## Responding with a response Most servers also do not respond with "Hello, World!" to every request. Instead they might respond with different headers, status codes, and body contents (even @@ -125,21 +117,24 @@ Deno.serve((req) => { }); ``` -> ℹ️ Note the `cancel` function here. This is called when the client hangs up -> the connection. This is important to make sure that you handle this case, as -> otherwise the server will keep queuing up messages forever, and eventually run -> out of memory. +ℹNote the `cancel` function above. This is called when the client hangs up the +connection. It is important to make sure that you handle this case, as otherwise +the server will keep queuing up messages forever, and eventually run out of +memory. + +Be aware that the response body stream is "cancelled" when the client hangs up +the connection. Make sure to handle this case. This can surface itself as an +error in a `write()` call on a `WritableStream` object that is attached to the +response body `ReadableStream` object (for example through a `TransformStream`). + +## HTTPS support -> ⚠️ Beware that the response body stream is "cancelled" when the client hangs -> up the connection. Make sure to handle this case. This can surface itself as -> an error in a `write()` call on a `WritableStream` object that is attached to -> the response body `ReadableStream` object (for example through a -> `TransformStream`). +:::note -### HTTPS support +To use HTTPS, you will need a valid TLS certificate and a private key for your +server. -> ℹ️ To use HTTPS, you will need a valid TLS certificate and a private key for -> your server. +::: To use HTTPS, pass two extra arguments in the options bag: `cert` and `key`. These are contents of the certificate and key files, respectively. @@ -152,15 +147,15 @@ Deno.serve({ }, handler); ``` -### HTTP/2 support +## HTTP/2 support HTTP/2 support is "automatic" when using the HTTP server APIs with Deno. You -just need to create your server, and the server will handle HTTP/1 or HTTP/2 -requests seamlessly. +just need to create your server, and it will handle HTTP/1 or HTTP/2 requests +seamlessly. HTTP/2 is also supported over cleartext with prior knowledge. -### Automatic body compression +## Automatic body compression The HTTP server has built in automatic compression of response bodies. When a response is sent to a client, Deno determines if the response body can be safely @@ -185,11 +180,11 @@ compressed if the following conditions are true: - The response body is greater than 64 bytes. When the response body is compressed, Deno will set the Content-Encoding header -to reflect the encoding as well as ensure the Vary header is adjusted or added -to indicate what request headers affected the response. +to reflect the encoding, as well as ensure the Vary header is adjusted or added +to indicate which request headers affected the response. -When is compression skipped? In addition to the logic above, there are a few -other reasons why a response won’t be compressed automatically: +In addition to the logic above, there are a few reasons why a response **won’t** +be compressed automatically: - The response contains a `Content-Encoding` header. This indicates your server has done some form of encoding already. @@ -205,34 +200,39 @@ other reasons why a response won’t be compressed automatically: value. This indicates that your server doesn’t want Deno or any downstream proxies to modify the response. -## `Deno.serveHttp` +## Deno.serveHttp -We generally recommend that you use the `Deno.serve` API described above, as it -handles all of the intricacies of parallel requests on a single connection, -error handling, and so on. However, if you are interested creating your own -robust and performant web servers in Deno, lower-level, _native_ HTTP server -APIs are available as of Deno 1.9 and later. +We recommend that you use the `Deno.serve` API described above, as it handles +all of the intricacies of parallel requests on a single connection, error +handling, and so on. However, if you are interested creating your own robust and +performant web servers in Deno, lower-level, _native_ HTTP server APIs are +available. -> ⚠️ You should probably not be using this API, as it is not easy to get right. -> Use the `Deno.serve` API instead. +:::warning -### Listening for a connection +You should probably not be using the `Deno.serveHTTP` API, as it is not easy to +get right. Use the `Deno.serve` API instead. + +::: + +## Listening for a connection In order to accept requests, first you need to listen for a connection on a -network port. To do this in Deno, you use `Deno.listen()`: +network port. To do this in Deno, you use +[`Deno.listen()`](/api/deno/~/Deno.listen): ```ts const server = Deno.listen({ port: 8080 }); ``` -> ℹ️ When supplying a port, Deno assumes you are going to listen on a TCP socket -> as well as bind to the localhost. You can specify `transport: "tcp"` to be -> more explicit as well as provide an IP address or hostname in the `hostname` -> property as well. +ℹWhen supplying a port, Deno assumes you are going to listen on a TCP socket as +well as bind to the localhost. You can specify `transport: "tcp"` to be more +explicit as well as provide an IP address or hostname in the `hostname` property +as well. If there is an issue with opening the network port, `Deno.listen()` will throw, -so often in a server sense, you will want to wrap it in the `try ... catch` -block in order to handle exceptions, like the port already being in use. +so often in a server sense, you will want to wrap it in a `try ... catch` block +in order to handle exceptions, such as the port already being in use. You can also listen for a TLS connection (e.g. HTTPS) using `Deno.listenTls()`: @@ -251,17 +251,14 @@ The `alpnProtocols` property is optional, but if you want to be able to support HTTP/2 on the server, you add the protocols here, as the protocol negotiation happens during the TLS negotiation with the client and server. -> ℹ️ Generating SSL certificates is outside of the scope of this documentation. -> There are many resources on the web which address this. - -### Handling connections +## Handling connections Once we are listening for a connection, we need to handle the connection. The return value of `Deno.listen()` or `Deno.listenTls()` is a `Deno.Listener` which is an async iterable which yields up `Deno.Conn` connections as well as provide a couple methods for handling connections. -To use it as an async iterable we would do something like this: +To use it as an async iterable you would do something like this: ```ts const server = Deno.listen({ port: 8080 }); @@ -271,10 +268,10 @@ for await (const conn of server) { } ``` -Every connection made would yield up a `Deno.Conn` assigned to `conn`. Then -further processing can be applied to the connection. +Every connection made would yield a `Deno.Conn` assigned to `conn`. Then further +processing can be applied to the connection. -There is also the `.accept()` method on the listener which can be used: +There is also an `.accept()` method on the listener which can be used: ```ts const server = Deno.listen({ port: 8080 }); @@ -292,13 +289,13 @@ while (true) { Whether using the async iterator or the `.accept()` method, exceptions can be thrown and robust production code should handle these using `try ... catch` -blocks. Especially when it comes to accepting TLS connections, there can be many +blocks. When it comes to accepting TLS connections, there can be many conditions, like invalid or unknown certificates which can be surfaced on the listener and might need handling in the user code. A listener also has a `.close()` method which can be used to close the listener. -### Serving HTTP +## Serving HTTP Once a connection is accepted, you can use `Deno.serveHttp()` to handle HTTP requests and responses on the connection. `Deno.serveHttp()` returns a @@ -374,7 +371,7 @@ In the examples from this point on, we will focus on what would occur within an example `handle()` function and remove the listening and connection "boilerplate". -#### HTTP Requests and Responses +### HTTP Requests and Responses HTTP requests and responses in Deno are essentially the inverse of web standard [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). The @@ -435,7 +432,7 @@ wondering how to send a particular response, checkout the documentation for the web standard [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response). -### HTTP/2 Support +## HTTP/2 Support HTTP/2 support is effectively transparent within the Deno runtime. Typically HTTP/2 is negotiated between a client and a server during the TLS connection @@ -463,7 +460,7 @@ HTTP/2 cleartext connection via the `Upgrade` header (see: [#10275](https://github.com/denoland/deno/issues/10275)), so therefore HTTP/2 support is only available via a TLS/HTTPS connection. -### Serving WebSockets +## Serving WebSockets Deno can upgrade incoming HTTP requests to a WebSocket. This allows you to handle WebSocket endpoints on your HTTP servers. diff --git a/runtime/manual/help.md b/runtime/manual/help.md index ede38525b..58c66e2db 100644 --- a/runtime/manual/help.md +++ b/runtime/manual/help.md @@ -1,5 +1,6 @@ --- title: "Where To Get Help" +oldUrl: /runtime/manual/help/ --- Stuck? Lost? Get Help from the Community. diff --git a/runtime/manual/runtime/builtin_apis.md b/runtime/manual/runtime/builtin_apis.md deleted file mode 100644 index 85775d94c..000000000 --- a/runtime/manual/runtime/builtin_apis.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "Deno Namespace APIs" -oldUrl: /runtime/manual/runtime/ ---- - -The global Deno namespace contains APIs that are not web standard, including -APIs for reading from files, opening TCP sockets, serving HTTP, and executing -subprocesses, etc. - -For a full list of Deno Built-in APIs, see the -[reference](https://docs.deno.com/api/deno/~/Deno). Below we highlight some of -the most important. - -## File System - -The Deno runtime comes with -[various functions for working with files and directories](https://docs.deno.com/api/deno/file-system). -You will need to use --allow-read and --allow-write permissions to gain access -to the file system. - -Refer to the links below for code examples of how to use the file system -functions. - -- [Reading files in several different ways](https://docs.deno.com/examples/reading-files) -- [Reading files in streams](../../tutorials/file_server.md) -- [Reading a text file (`Deno.readTextFile`)](../../tutorials/read_write_files.md#reading-a-text-file) -- [Writing a text file (`Deno.writeTextFile`)](../../tutorials/read_write_files.md#writing-a-text-file) - -## Network - -The Deno runtime comes with -[built-in functions for dealing with connections to network ports](https://docs.deno.com/api/deno/network). - -Refer to the links below for code examples for common functions. - -- [Connect to the hostname and port (`Deno.connect`)](https://docs.deno.com/api/deno/~/Deno.connect) -- [Announcing on the local transport address (`Deno.listen`)](https://docs.deno.com/api/deno/~/Deno.listen) - -## Subprocesses - -The Deno runtime comes with -[built-in functions for spinning up subprocesses](https://docs.deno.com/api/deno/sub-process). - -Refer to the links below for code samples of how to create a subprocess. - -- [Creating a subprocess (`Deno.Command`)](../../tutorials/subprocess.md) - -## Errors - -The Deno runtime comes with -[20 error classes](https://docs.deno.com/api/deno/errors) that can be raised in -response to a number of conditions. - -Some examples are: - -```sh -Deno.errors.NotFound; -Deno.errors.WriteZero; -``` - -They can be used as below: - -```ts -try { - const file = await Deno.open("./some/file.txt"); -} catch (error) { - if (error instanceof Deno.errors.NotFound) { - console.error("the file was not found"); - } else { - // otherwise re-throw - throw error; - } -} -``` diff --git a/runtime/manual/runtime/ffi_api.md b/runtime/manual/runtime/ffi_api.md deleted file mode 100644 index 53863360b..000000000 --- a/runtime/manual/runtime/ffi_api.md +++ /dev/null @@ -1,292 +0,0 @@ ---- -title: "Foreign Function Interface" ---- - -As of Deno 1.13 and later, the FFI (foreign function interface) API allows users -to call libraries written in native languages that support the C ABIs (C/C++, -Rust, Zig, V, etc.) using `Deno.dlopen`. - -## Usage - -Here's an example showing how to call a Rust function from Deno: - -```rust -// add.rs -#[no_mangle] -pub extern "C" fn add(a: isize, b: isize) -> isize { - a + b -} -``` - -Compile it to a C dynamic library (`libadd.so` on Linux): - -```sh -rustc --crate-type cdylib add.rs -``` - -In C you can write it as: - -```c -// add.c -int add(int a, int b) { - return a + b; -} -``` - -And compile it: - -```sh -// unix -cc -c -o add.o add.c -cc -shared -W -o libadd.so add.o -// Windows -cl /LD add.c /link /EXPORT:add -``` - -Calling the library from Deno: - -```typescript -// ffi.ts - -// Determine library extension based on -// your OS. -let libSuffix = ""; -switch (Deno.build.os) { - case "windows": - libSuffix = "dll"; - break; - case "darwin": - libSuffix = "dylib"; - break; - default: - libSuffix = "so"; - break; -} - -const libName = `./libadd.${libSuffix}`; -// Open library and define exported symbols -const dylib = Deno.dlopen( - libName, - { - "add": { parameters: ["isize", "isize"], result: "isize" }, - } as const, -); - -// Call the symbol `add` -const result = dylib.symbols.add(35, 34); // 69 - -console.log(`Result from external addition of 35 and 34: ${result}`); -``` - -Run with `--allow-ffi` and `--unstable` flag: - -```sh -deno run --allow-ffi --unstable ffi.ts -``` - -## Non-blocking FFI - -There are many use cases where users might want to run CPU-bound FFI functions -in the background without blocking other tasks on the main thread. - -As of Deno 1.15, symbols can be marked `nonblocking` in `Deno.dlopen`. These -function calls will run on a dedicated blocking thread and will return a -`Promise` resolving to the desired `result`. - -Example of executing expensive FFI calls with Deno: - -```c -// sleep.c -#ifdef _WIN32 -#include -#else -#include -#endif - -int sleep(unsigned int ms) { - #ifdef _WIN32 - Sleep(ms); - #else - struct timespec ts; - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000; - nanosleep(&ts, NULL); - #endif -} -``` - -Calling it from Deno: - -```typescript -// nonblocking_ffi.ts -const library = Deno.dlopen( - "./sleep.so", - { - sleep: { - parameters: ["usize"], - result: "void", - nonblocking: true, - }, - } as const, -); - -library.symbols.sleep(500).then(() => console.log("After")); -console.log("Before"); -``` - -Result: - -```sh -$ deno run --allow-ffi --unstable unblocking_ffi.ts -Before -After -``` - -## Callbacks - -Deno FFI API supports creating C callbacks from JavaScript functions for calling -back into Deno from dynamic libraries. An example of how callbacks are created -and used is as follows: - -```typescript -// callback_ffi.ts -const library = Deno.dlopen( - "./callback.so", - { - set_status_callback: { - parameters: ["function"], - result: "void", - }, - start_long_operation: { - parameters: [], - result: "void", - }, - check_status: { - parameters: [], - result: "void", - }, - } as const, -); - -const callback = new Deno.UnsafeCallback( - { - parameters: ["u8"], - result: "void", - } as const, - (success: number) => {}, -); - -// Pass the callback pointer to dynamic library -library.symbols.set_status_callback(callback.pointer); -// Start some long operation that does not block the thread -library.symbols.start_long_operation(); - -// Later, trigger the library to check if the operation is done. -// If it is, this call will trigger the callback. -library.symbols.check_status(); -``` - -If an `UnsafeCallback`'s callback function throws an error, the error will get -propagated up to the function that triggered the callback to be called (above, -that would be `check_status()`) and can be caught there. If a callback returning -a value throws then Deno will return 0 (null pointer for pointers) as the -result. - -`UnsafeCallback` is not deallocated by default as it can cause use-after-free -bugs. To properly dispose of an `UnsafeCallback` its `close()` method must be -called. - -```typescript -const callback = new Deno.UnsafeCallback( - { parameters: [], result: "void" } as const, - () => {}, -); - -// After callback is no longer needed -callback.close(); -// It is no longer safe to pass the callback as a parameter. -``` - -It is also possible for native libraries to setup interrupt handlers and to have -those directly trigger the callback. However, this is not recommended and may -cause unexpected side-effects and undefined behaviour. Preferably any interrupt -handlers would only set a flag that can later be polled similarly to how -`check_status()` is used above. - -## Supported types - -Here's a list of types supported currently by the Deno FFI API. - -| FFI Type | Deno | C | Rust | -| ---------------------- | -------------------- | ------------------------ | ------------------------- | -| `i8` | `number` | `char` / `signed char` | `i8` | -| `u8` | `number` | `unsigned char` | `u8` | -| `i16` | `number` | `short int` | `i16` | -| `u16` | `number` | `unsigned short int` | `u16` | -| `i32` | `number` | `int` / `signed int` | `i32` | -| `u32` | `number` | `unsigned int` | `u32` | -| `i64` | `number \| bigint` | `long long int` | `i64` | -| `u64` | `number \| bigint` | `unsigned long long int` | `u64` | -| `usize` | `number \| bigint` | `size_t` | `usize` | -| `isize` | `number \| bigint` | `size_t` | `isize` | -| `f32` | `number \| bigint` | `float` | `f32` | -| `f64` | `number \| bigint` | `double` | `f64` | -| `void`[1] | `undefined` | `void` | `()` | -| `pointer` | `{} \| null` | `void *` | `*mut c_void` | -| `buffer`[2] | `TypedArray \| null` | `uint8_t *` | `*mut u8` | -| `function`[3] | `{} \| null` | `void (*fun)()` | `Option` | -| `{ struct: [...] }`[4] | `TypedArray` | `struct MyStruct` | `MyStruct` | - -As of Deno 1.25, the `pointer` type has been split into a `pointer` and a -`buffer` type to ensure users take advantage of optimizations for Typed Arrays, -and as of Deno 1.31 the JavaScript representation of `pointer` has become an -opaque pointer object or `null` for null pointers. - -- [1] `void` type can only be used as a result type. -- [2] `buffer` type accepts TypedArrays as parameter, but it always returns a - pointer object or `null` when used as result type like the `pointer` type. -- [3] `function` type works exactly the same as the `pointer` type as a - parameter and result type. -- [4] `struct` type is for passing and returning C structs by value (copy). The - `struct` array must enumerate each of the struct's fields' type in order. The - structs are padded automatically: Packed structs can be defined by using an - appropriate amount of `u8` fields to avoid padding. Only TypedArrays are - supported as structs, and structs are always returned as `Uint8Array`s. - -## deno_bindgen - -[`deno_bindgen`](https://github.com/denoland/deno_bindgen) is the official tool -to simplify glue code generation of Deno FFI libraries written in Rust. - -It is similar to [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) in -the Rust WASM ecosystem. - -Here's an example showing its usage: - -```rust -// mul.rs -use deno_bindgen::deno_bindgen; - -#[deno_bindgen] -struct Input { - a: i32, - b: i32, -} - -#[deno_bindgen] -fn mul(input: Input) -> i32 { - input.a * input.b -} -``` - -Run `deno_bindgen` to generate bindings. You can now directly import them into -Deno: - -```ts -// mul.ts -import { mul } from "./bindings/bindings.ts"; -mul({ a: 10, b: 2 }); // 20 -``` - -Any issues related to `deno_bindgen` should be reported at -https://github.com/denoland/deno_bindgen/issues diff --git a/runtime/manual/runtime/import_meta_api.md b/runtime/manual/runtime/import_meta_api.md deleted file mode 100644 index 3ed8473ef..000000000 --- a/runtime/manual/runtime/import_meta_api.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: "`import.meta` API" ---- - -Deno supports a number of properties and methods on the -[`import.meta`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta) -API. It can be used to get information about the module like the module's URL. - -## `import.meta.url` - -Returns the URL of the current module. - -```ts title="main.ts" -console.log(import.meta.url); -``` - -```sh -$ deno run main.ts -file:///dev/main.ts - -$ deno run https:/example.com/main.ts -https://example.com/main.ts -``` - -## `import.meta.main` - -Returns whether the current module is the entry point to your program. - -```ts title="main.ts" -import "./other.ts"; - -console.log(`Is ${import.meta.url} the main module?`, import.meta.main); -``` - -```ts title="other.ts" -console.log(`Is ${import.meta.url} the main module?`, import.meta.main); -``` - -```sh -$ deno run main.ts -Is file:///dev/other.ts the main module? false -Is file:///dev/main.ts the main module? true -``` - -## `import.meta.filename` - -_This property is only available for local modules (module that have -`file:///...` specifier) and returns `undefined` for remote modules._ - -Returns the fully resolved path to the current module. The value contains OS -specific path separators. - -```ts title="main.ts" -console.log(import.meta.filename); -``` - -On Unix: - -```sh -$ deno run main.ts -/dev/main.ts - -$ deno run https://example.com/main.ts -undefined -``` - -On Windows: - -```sh -$ deno run main.ts -C:\dev\main.ts - -$ deno run https://example.com/main.ts -undefined -``` - -## `import.meta.dirname` - -_This property is only available for local modules (module that have -`file:///...` specifier) and returns `undefined` for remote modules._ - -Returns the fully resolved path to the directory containing the current module. -The value contains OS specific path separators. - -```ts title="main.ts" -console.log(import.meta.dirname); -``` - -On Unix: - -```sh -$ deno run main.ts -/dev/ - -$ deno run https://example.com/main.ts -undefined -``` - -On Windows: - -```sh -$ deno run main.ts -C:\dev\ - -$ deno run https://example.com/main.ts -undefined -``` - -## `import.meta.resolve` - -Resolve specifiers relative to the current module. - -```ts -const worker = new Worker(import.meta.resolve("./worker.ts")); -``` - -The `import.meta.resolve` API takes into account the currently applied import -map, which gives you the ability to resolve "bare" specifiers as well. - -With such import map loaded... - -```json -{ - "imports": { - "fresh": "https://deno.land/x/fresh@1.0.1/dev.ts" - } -} -``` - -...you can now resolve: - -```js title="resolve.js" -console.log(import.meta.resolve("fresh")); -``` - -```sh -$ deno run resolve.js -https://deno.land/x/fresh@1.0.1/dev.ts -``` diff --git a/runtime/manual/runtime/index.md b/runtime/manual/runtime/index.md deleted file mode 100644 index 0f3bc68e2..000000000 --- a/runtime/manual/runtime/index.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Runtime" ---- - -Documentation for all runtime functions (Web APIs + `Deno` global + Node APIs) -can be found at [`/api`](https://docs.deno.com/api/deno/). - -## Web Platform APIs - -For APIs where a web standard already exists, like `fetch` for HTTP requests, -Deno uses these rather than inventing a new proprietary API. - -For more details, view the chapter on -[Web Platform APIs](./web_platform_apis.md). - -## `Deno` global - -All APIs that are not web standard are contained in the global `Deno` namespace. -It has the APIs for reading from files, opening TCP sockets, -[serving HTTP](./http_server_apis.md), and executing subprocesses, etc. - -For more details, view the chapter on [Built-in APIs](./builtin_apis.md). - -The TypeScript definitions for the Deno namespaces can be found in the -[`lib.deno.ns.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.ns.d.ts) -file. - -## Node APIs - -Deno also provides compatibility with Node.js APIs. For example, the `node:fs` -module can be imported and used in Deno, like it would be in Node.js. - -For more details, view the chapter on -[Node Compatibility](../node/node_specifiers.md). diff --git a/runtime/manual/runtime/location_api.md b/runtime/manual/runtime/location_api.md deleted file mode 100644 index 8e35e545b..000000000 --- a/runtime/manual/runtime/location_api.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: "Location API" ---- - -Deno supports the -[`location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location) -global from the web. Please read on. - -## Location flag - -There is no "web page" whose URL we can use for a location in a Deno process. We -instead allow users to emulate a document location by specifying one on the CLI -using the `--location` flag. It can be a `http` or `https` URL. - -```ts -// deno run --location https://example.com/path main.ts - -console.log(location.href); -// "https://example.com/path" -``` - -You must pass `--location ` for this to work. If you don't, any access to -the `location` global will throw an error. - -```ts -// deno run main.ts - -console.log(location.href); -// error: Uncaught ReferenceError: Access to "location", run again with --location . -``` - -Setting `location` or any of its fields will normally cause navigation in -browsers. This is not applicable in Deno, so it will throw in this situation. - -```ts -// deno run --location https://example.com/path main.ts - -location.pathname = "./foo"; -// error: Uncaught NotSupportedError: Cannot set "location.pathname". -``` - -## Extended usage - -On the web, resource resolution (excluding modules) typically uses the value of -`location.href` as the root on which to base any relative URLs. This affects -some web APIs adopted by Deno. - -### Fetch API - -```ts -// deno run --location https://api.github.com/ --allow-net main.ts - -const response = await fetch("./orgs/denoland"); -// Fetches "https://api.github.com/orgs/denoland". -``` - -The `fetch()` call above would throw if the `--location` flag was not passed, -since there is no web-analogous location to base it onto. - -### Worker modules - -```ts -// deno run --location https://example.com/index.html --allow-net main.ts - -const worker = new Worker("./workers/hello.ts", { type: "module" }); -// Fetches worker module at "https://example.com/workers/hello.ts". -``` - -## Only use if necessary - -For the above use cases, it is preferable to pass URLs in full rather than -relying on `--location`. You can manually base a relative URL using the `URL` -constructor if needed. - -The `--location` flag is intended for those who have some specific purpose in -mind for emulating a document location and are aware that this will only work at -application-level. However, you may also use it to silence errors from a -dependency which is frivolously accessing the `location` global. diff --git a/runtime/manual/runtime/permission_apis.md b/runtime/manual/runtime/permission_apis.md deleted file mode 100644 index dabbd24cc..000000000 --- a/runtime/manual/runtime/permission_apis.md +++ /dev/null @@ -1,213 +0,0 @@ ---- -title: "Permission APIs" ---- - -Permissions are granted from the CLI when running the `deno` command. User code -will often assume its own set of required permissions, but there is no guarantee -during execution that the set of _granted_ permissions will align with this. - -In some cases, ensuring a fault-tolerant program requires a way to interact with -the permission system at runtime. - -## Permission descriptors - -On the CLI, read permission for `/foo/bar` is represented as -`--allow-read=/foo/bar`. In runtime JS, it is represented as the following: - -```ts -const desc = { name: "read", path: "/foo/bar" } as const; -``` - -Other examples: - -```ts -// Global write permission. -const desc1 = { name: "write" } as const; - -// Write permission to `$PWD/foo/bar`. -const desc2 = { name: "write", path: "foo/bar" } as const; - -// Global net permission. -const desc3 = { name: "net" } as const; - -// Net permission to 127.0.0.1:8000. -const desc4 = { name: "net", host: "127.0.0.1:8000" } as const; - -// High-resolution time permission. -const desc5 = { name: "hrtime" } as const; -``` - -> ⚠️ See -> [`PermissionDescriptor`](https://docs.deno.com/api/deno/~/Deno.PermissionDescriptor) -> in API reference for more details. - -> ⚠️ In 1.30 and onwards, synchronous API counterparts (ex. -> `Deno.permissions.querySync`) exist for all the APIs described below. - -## Query permissions - -Check, by descriptor, if a permission is granted or not. - -```ts -// deno run --allow-read=/foo main.ts - -const desc1 = { name: "read", path: "/foo" } as const; -console.log(await Deno.permissions.query(desc1)); -// PermissionStatus { state: "granted", partial: false } - -const desc2 = { name: "read", path: "/foo/bar" } as const; -console.log(await Deno.permissions.query(desc2)); -// PermissionStatus { state: "granted", partial: false } - -const desc3 = { name: "read", path: "/bar" } as const; -console.log(await Deno.permissions.query(desc3)); -// PermissionStatus { state: "prompt", partial: false } -``` - -If `--deny-read` flag was used to restrict some of the filepaths, the result -will contain `partial: true` describing that not all subpaths have permissions -granted: - -```ts -// deno run --allow-read=/foo --deny-read=/foo/bar main.ts - -const desc1 = { name: "read", path: "/foo" } as const; -console.log(await Deno.permissions.query(desc1)); -// PermissionStatus { state: "granted", partial: true } - -const desc2 = { name: "read", path: "/foo/bar" } as const; -console.log(await Deno.permissions.query(desc2)); -// PermissionStatus { state: "denied", partial: false } - -const desc3 = { name: "read", path: "/bar" } as const; -console.log(await Deno.permissions.query(desc3)); -// PermissionStatus { state: "prompt", partial: false } -``` - -## Permission states - -A permission state can be either "granted", "prompt" or "denied". Permissions -which have been granted from the CLI will query to `{ state: "granted" }`. Those -which have not been granted query to `{ state: "prompt" }` by default, while -`{ state: "denied" }` reserved for those which have been explicitly refused. -This will come up in [Request permissions](#request-permissions). - -## Permission strength - -The intuitive understanding behind the result of the second query in -[Query permissions](#query-permissions) is that read access was granted to -`/foo` and `/foo/bar` is within `/foo` so `/foo/bar` is allowed to be read. This -hold true, unless the CLI-granted permission is _partial_ to the queried -permissions (as an effect of using a `--deny-*` flag). - -We can also say that `desc1` is -_[stronger than](https://www.w3.org/TR/permissions/#ref-for-permissiondescriptor-stronger-than)_ -`desc2`. This means that for any set of CLI-granted permissions: - -1. If `desc1` queries to `{ state: "granted", partial: false }` then so must - `desc2`. -2. If `desc2` queries to `{ state: "denied", partial: false }` then so must - `desc1`. - -More examples: - -```ts -const desc1 = { name: "write" } as const; -// is stronger than -const desc2 = { name: "write", path: "/foo" } as const; - -const desc3 = { name: "net", host: "127.0.0.1" } as const; -// is stronger than -const desc4 = { name: "net", host: "127.0.0.1:8000" } as const; -``` - -## Request permissions - -Request an ungranted permission from the user via CLI prompt. - -```ts -// deno run main.ts - -const desc1 = { name: "read", path: "/foo" } as const; -const status1 = await Deno.permissions.request(desc1); -// ⚠️ Deno requests read access to "/foo". Grant? [y/n (y = yes allow, n = no deny)] y -console.log(status1); -// PermissionStatus { state: "granted", partial: false } - -const desc2 = { name: "read", path: "/bar" } as const; -const status2 = await Deno.permissions.request(desc2); -// ⚠️ Deno requests read access to "/bar". Grant? [y/n (y = yes allow, n = no deny)] n -console.log(status2); -// PermissionStatus { state: "denied", partial: false } -``` - -If the current permission state is "prompt", a prompt will appear on the user's -terminal asking them if they would like to grant the request. The request for -`desc1` was granted so its new status is returned and execution will continue as -if `--allow-read=/foo` was specified on the CLI. The request for `desc2` was -denied so its permission state is downgraded from "prompt" to "denied". - -If the current permission state is already either "granted" or "denied", the -request will behave like a query and just return the current status. This -prevents prompts both for already granted permissions and previously denied -requests. - -## Revoke permissions - -Downgrade a permission from "granted" to "prompt". - -```ts -// deno run --allow-read=/foo main.ts - -const desc = { name: "read", path: "/foo" } as const; -console.log(await Deno.permissions.revoke(desc)); -// PermissionStatus { state: "prompt", partial: false } -``` - -What happens when you try to revoke a permission which is _partial_ to one -granted on the CLI? - -```ts -// deno run --allow-read=/foo main.ts - -const desc = { name: "read", path: "/foo/bar" } as const; -console.log(await Deno.permissions.revoke(desc)); -// PermissionStatus { state: "prompt", partial: false } -const cliDesc = { name: "read", path: "/foo" } as const; -console.log(await Deno.permissions.revoke(cliDesc)); -// PermissionStatus { state: "prompt", partial: false } -``` - -The CLI-granted permission, which implies the revoked permission, was also -revoked. - -To understand this behaviour, imagine that Deno stores an internal set of -_explicitly granted permission descriptors_. Specifying `--allow-read=/foo,/bar` -on the CLI initializes this set to: - -```ts -[ - { name: "read", path: "/foo" }, - { name: "read", path: "/bar" }, -]; -``` - -Granting a runtime request for `{ name: "write", path: "/foo" }` updates the set -to: - -```ts -[ - { name: "read", path: "/foo" }, - { name: "read", path: "/bar" }, - { name: "write", path: "/foo" }, -]; -``` - -Deno's permission revocation algorithm works by removing every element from this -set which is _stronger than_ the argument permission descriptor. - -Deno does not allow "fragmented" permission states, where some strong permission -is granted with exclusions of weak permissions implied by it. Such a system -would prove increasingly complex and unpredictable as you factor in a wider -variety of use cases and the `"denied"` state. This is a calculated trade-off of -granularity for security. diff --git a/runtime/manual/runtime/program_lifecycle.md b/runtime/manual/runtime/program_lifecycle.md deleted file mode 100644 index 89e32e8c8..000000000 --- a/runtime/manual/runtime/program_lifecycle.md +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: "Program Lifecycle" ---- - -Deno supports browser compatible lifecycle events: - -- [`load`](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event#:~:text=The%20load%20event%20is%20fired,for%20resources%20to%20finish%20loading.): - fired when the whole page has loaded, including all dependent resources such - as stylesheets and images. -- [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event#:~:text=The%20beforeunload%20event%20is%20fired,want%20to%20leave%20the%20page.): - fired when the event loop has no more work to do and is about to exit. - Scheduling more asynchronous work (like timers or network requests) will cause - the program to continue. -- [`unload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event): - fired when the document or a child resource is being unloaded. -- [`unhandledrejection`](https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event): - fired when a promise that has no rejection handler is rejected, ie. a promise - that has no `.catch()` handler or a second argument to `.then()`. -- [`rejectionhandled`](https://developer.mozilla.org/en-US/docs/Web/API/Window/rejectionhandled_event): - fired when a `.catch()` handler is added to a a promise that has already - rejected. This event is fired only if there's `unhandledrejection` listener - installed that prevents propagation of the event (which would result in the - program terminating with an error). - -You can use these events to provide setup and cleanup code in your program. - -Listeners for `load` events can be asynchronous and will be awaited, this event -cannot be canceled. Listeners for `beforeunload` need to be synchronous and can -be cancelled to keep the program running. Listeners for `unload` events need to -be synchronous and cannot be cancelled. - -## Example - -**main.ts** - -```ts -import "./imported.ts"; - -const handler = (e: Event): void => { - console.log(`got ${e.type} event in event handler (main)`); -}; - -globalThis.addEventListener("load", handler); - -globalThis.addEventListener("beforeunload", handler); - -globalThis.addEventListener("unload", handler); - -globalThis.onload = (e: Event): void => { - console.log(`got ${e.type} event in onload function (main)`); -}; - -globalThis.onbeforeunload = (e: Event): void => { - console.log(`got ${e.type} event in onbeforeunload function (main)`); -}; - -globalThis.onunload = (e: Event): void => { - console.log(`got ${e.type} event in onunload function (main)`); -}; - -console.log("log from main script"); -``` - -**imported.ts** - -```ts -const handler = (e: Event): void => { - console.log(`got ${e.type} event in event handler (imported)`); -}; - -globalThis.addEventListener("load", handler); -globalThis.addEventListener("beforeunload", handler); -globalThis.addEventListener("unload", handler); - -globalThis.onload = (e: Event): void => { - console.log(`got ${e.type} event in onload function (imported)`); -}; - -globalThis.onbeforeunload = (e: Event): void => { - console.log(`got ${e.type} event in onbeforeunload function (imported)`); -}; - -globalThis.onunload = (e: Event): void => { - console.log(`got ${e.type} event in onunload function (imported)`); -}; - -console.log("log from imported script"); -``` - -A couple notes on this example: - -- `addEventListener` and `onload`/`onunload` are prefixed with `globalThis`, but - you could also use `self` or no prefix at all. - [It is not recommended to use `window` as a prefix](https://lint.deno.land/#no-window-prefix). -- You can use `addEventListener` and/or `onload`/`onunload` to define handlers - for events. There is a major difference between them, let's run the example: - -```shell -$ deno run main.ts -log from imported script -log from main script -got load event in event handler (imported) -got load event in event handler (main) -got load event in onload function (main) -got onbeforeunload event in event handler (imported) -got onbeforeunload event in event handler (main) -got onbeforeunload event in onbeforeunload function (main) -got unload event in event handler (imported) -got unload event in event handler (main) -got unload event in onunload function (main) -``` - -All listeners added using `addEventListener` were run, but `onload`, -`onbeforeunload` and `onunload` defined in `main.ts` overrode handlers defined -in `imported.ts`. - -In other words, you can use `addEventListener` to register multiple `"load"` or -`"unload"` event handlers, but only the last defined `onload`, `onbeforeunload`, -`onunload` event handlers will be executed. It is preferable to use -`addEventListener` when possible for this reason. - -## `beforeunload` Example - -```js -// beforeunload.js -let count = 0; - -console.log(count); - -globalThis.addEventListener("beforeunload", (e) => { - console.log("About to exit..."); - if (count < 4) { - e.preventDefault(); - console.log("Scheduling more work..."); - setTimeout(() => { - console.log(count); - }, 100); - } - - count++; -}); - -globalThis.addEventListener("unload", (e) => { - console.log("Exiting"); -}); - -count++; -console.log(count); - -setTimeout(() => { - count++; - console.log(count); -}, 100); -``` - -Running this program will print: - -```sh -$ deno run beforeunload.js -0 -1 -2 -About to exit... -Scheduling more work... -3 -About to exit... -Scheduling more work... -4 -About to exit... -Exiting -``` - -This has allowed us to polyfill `process.on("beforeExit")` in the Node -compatibility layer. - -## `unhandledrejection` event Example: - -This release adds support for the unhandledrejection event. This event is fired -when a promise that has no rejection handler is rejected, ie. a promise that has -no .catch() handler or a second argument to .then(). - -```js -// unhandledrejection.js -globalThis.addEventListener("unhandledrejection", (e) => { - console.log("unhandled rejection at:", e.promise, "reason:", e.reason); - e.preventDefault(); -}); - -function Foo() { - this.bar = Promise.reject(new Error("bar not available")); -} - -new Foo(); -Promise.reject(); -``` - -Running this program will print: - -```sh -$ deno run unhandledrejection.js -unhandled rejection at: Promise { - Error: bar not available - at new Foo (file:///dev/unhandled_rejection.js:7:29) - at file:///dev/unhandled_rejection.js:10:1 -} reason: Error: bar not available - at new Foo (file:///dev/unhandled_rejection.js:7:29) - at file:///dev/unhandled_rejection.js:10:1 -unhandled rejection at: Promise { undefined } reason: undefined -``` - -This API will allow us to polyfill `process.on("unhandledRejection")` in the -Node compatibility layer in future releases. diff --git a/runtime/manual/runtime/web_platform_apis.md b/runtime/manual/runtime/web_platform_apis.md deleted file mode 100644 index 6bd896444..000000000 --- a/runtime/manual/runtime/web_platform_apis.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: "Using Web Platform APIs" -oldUrl: - - /runtime/manual/runtime/navigator_api/ - - /manual/runtime/web_platform_apis/ ---- - -One way Deno simplifies web and cloud development is by using Web Platform APIs -(like `fetch`) over proprietary APIs. This means if you've ever built for the -browser, you're likely already familiar with Deno, and if you're learning Deno, -you're also investing in your knowledge of the web. - -## Supported APIs - -Here's a partial list of supported web platform APIs in Deno: - -- [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) -- [BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) -- [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) -- [Channel Messaging API](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API) -- [Compression Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Compression_Streams_API) -- [Console](https://developer.mozilla.org/en-US/docs/Web/API/Console) -- [Event API](https://docs.deno.com/api/web/events) -- [Encoding API](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API) -- [Fetch API](#fetch-api) -- [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) -- [Location API](./location_api.md) -- [`navigator.language` API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language) -- [Performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance) -- [`setTimeout`, `setInterval`, `clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) -- [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) -- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) -- [`URLPattern`](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) -- [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) -- [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) -- [Web File API](https://developer.mozilla.org/en-US/docs/Web/API/File_API) -- [Web Storage API](./web_storage_api.md) -- [Web Workers API](https://developer.mozilla.org/en-US/docs/Web/API/Worker) -- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) - -You can find the Deno reference for these APIs -[here](https://docs.deno.com/api/web/). To check if a Web Platform API is -available in Deno, click on -[the interface on MDN](https://developer.mozilla.org/en-US/docs/Web/API#interfaces) -and refer to -[its Browser Compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/AbortController#browser_compatibility) -(link as an example). - -## `fetch` API - -## Overview - -The `fetch` API can be used to make HTTP requests. It is implemented as -specified in the [WHATWG `fetch` spec](https://fetch.spec.whatwg.org/). - -You can find documentation about this API on -[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). - -## Spec deviations - -- The Deno user agent does not have a cookie jar. As such, the `set-cookie` - header on a response is not processed, or filtered from the visible response - headers. -- Deno does not follow the same-origin policy, because the Deno user agent - currently does not have the concept of origins, and it does not have a cookie - jar. This means Deno does not need to protect against leaking authenticated - data cross origin. Because of this Deno does not implement the following - sections of the WHATWG `fetch` specification: - - Section `3.1. 'Origin' header`. - - Section `3.2. CORS protocol`. - - Section `3.5. CORB`. - - Section `3.6. 'Cross-Origin-Resource-Policy' header`. - - `Atomic HTTP redirect handling`. - - The `opaqueredirect` response type. -- A `fetch` with a `redirect` mode of `manual` will return a `basic` response - rather than an `opaqueredirect` response. -- The specification is vague on how - [`file:` URLs are to be handled](https://fetch.spec.whatwg.org/#scheme-fetch). - Firefox is the only mainstream browser that implements fetching `file:` URLs, - and even then it doesn't work by default. As of Deno 1.16, Deno supports - fetching local files. See the next section for details. -- The `request` and `response` header guards are implemented, but unlike - browsers do not have any constraints on which header names are allowed. -- The `referrer`, `referrerPolicy`, `mode`, `credentials`, `cache`, `integrity`, - `keepalive`, and `window` properties and their relevant behaviours in - `RequestInit` are not implemented. The relevant fields are not present on the - `Request` object. -- Request body upload streaming is supported (on HTTP/1.1 and HTTP/2). Unlike - the current fetch proposal, the implementation supports duplex streaming. -- The `set-cookie` header is not concatenated when iterated over in the - `headers` iterator. This behaviour is in the - [process of being specified](https://github.com/whatwg/fetch/pull/1346). - -## Fetching local files - -As of Deno 1.16, Deno supports fetching `file:` URLs. This makes it easier to -write code that uses the same code path on a server as local, as well as easier -to author code that works both with the Deno CLI and Deno Deploy. - -Deno only supports absolute file URLs, this means that `fetch("./some.json")` -will not work. It should be noted though that if -[`--location`](./location_api.md) is specified, relative URLs use the -`--location` as the base, but a `file:` URL cannot be passed as the -`--location`. - -To be able to fetch some resource, relative to the current module, which would -work if the module is local or remote, you would want to use `import.meta.url` -as the base. For example, something like: - -```js -const response = await fetch(new URL("./config.json", import.meta.url)); -const config = await response.json(); -``` - -Notes on fetching local files: - -- Permissions are applied to reading resources, so an appropriate `--allow-read` - permission is needed to be able to read a local file. -- Fetching locally only supports the `GET` method, and will reject the promise - with any other method. -- A file that does not exist simply rejects the promise with a vague - `TypeError`. This is to avoid the potential of fingerprinting attacks. -- No headers are set on the response. Therefore it is up to the consumer to - determine things like the content type or content length. -- Response bodies are streamed from the Rust side, so large files are available - in chunks, and can be cancelled. - -## `CustomEvent` and `EventTarget` - -## Overview - -The DOM Event API can be used to dispatch and listen to events happening in an -application. It is implemented as specified in the -[WHATWG DOM spec](https://dom.spec.whatwg.org/#events). - -You can find documentation about this API on -[MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget). - -## Spec deviations - -- Events do not bubble, because Deno does not have a DOM hierarchy, so there is - no tree for Events to bubble/capture through. -- `timeStamp` property is always set to `0`. - ---- - -## Typings - -The TypeScript definitions for the implemented web APIs can be found in the -[`lib.deno.shared_globals.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.shared_globals.d.ts) -and -[`lib.deno.window.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.window.d.ts) -files. - -Definitions that are specific to workers can be found in the -[`lib.deno.worker.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.worker.d.ts) -file. - -## Deviations of other APIs from spec - -### Cache API - -Only the following APIs are implemented: - -- [CacheStorage::open()](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/open) -- [CacheStorage::has()](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/has) -- [CacheStorage::delete()](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/delete) -- [Cache::match()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match) -- [Cache::put()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/put) -- [Cache::delete()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete) - -A few things that are different compared to browsers: - -1. You cannot pass relative paths to the APIs. The request can be an instance of - Request or URL or a url string. -2. `match()` & `delete()` don't support query options yet. diff --git a/runtime/manual/runtime/web_storage_api.md b/runtime/manual/runtime/web_storage_api.md deleted file mode 100644 index 49b5c42e2..000000000 --- a/runtime/manual/runtime/web_storage_api.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: "Web Storage API" ---- - -Deno 1.10 introduced the -[Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) -which provides an API for storing string keys and values. Persisting data works -similar to a browser, and has a 10MB storage limit. The global `sessionStorage` -object only persists data for the current execution context, while -`localStorage` persists data from execution to execution. - -In a browser, `localStorage` persists data uniquely per origin (effectively the -protocol plus hostname plus port). As of Deno 1.16, Deno has a set of rules to -determine what is a unique storage location: - -- When using the `--location` flag, the origin for the location is used to - uniquely store the data. That means a location of `http://example.com/a.ts` - and `http://example.com/b.ts` and `http://example.com:80/` would all share the - same storage, but `https://example.com/` would be different. -- If there is no location specifier, but there is a `--config` configuration - file specified, the absolute path to that configuration file is used. That - means `deno run --config deno.jsonc a.ts` and - `deno run --config deno.jsonc b.ts` would share the same storage, but - `deno run --config tsconfig.json a.ts` would be different. -- If there is no configuration or location specifier, Deno uses the absolute - path to the main module to determine what storage is shared. The Deno REPL - generates a "synthetic" main module that is based off the current working - directory where `deno` is started from. This means that multiple invocations - of the REPL from the same path will share the persisted `localStorage` data. - -This means, unlike versions prior to 1.16, `localStorage` is always available in -the main process. - -## Example - -The following snippet accesses the local storage bucket for the current origin -and adds a data item to it using `setItem()`. - -```ts -localStorage.setItem("myDemo", "Deno App"); -``` - -The syntax for reading the localStorage item is as follows: - -```ts -const cat = localStorage.getItem("myDemo"); -``` - -The syntax for removing the localStorage item is as follows: - -```ts -localStorage.removeItem("myDemo"); -``` - -The syntax for removing all the localStorage items is as follows: - -```ts -localStorage.clear(); -``` diff --git a/runtime/manual/runtime/webassembly/index.md b/runtime/manual/runtime/webassembly/index.md deleted file mode 100644 index 951454a84..000000000 --- a/runtime/manual/runtime/webassembly/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "Using WebAssembly" -oldUrl: - - /runtime/manual/getting_started/webassembly/ ---- - -Designed to be used alongside JavaScript to speed up key application components, -[WebAssembly](https://webassembly.org/) can have much higher, and more -consistent execution speed than JavaScript, similar to C, C++, or Rust. Deno can -execute WebAssembly modules with the same interfaces that -[browsers provide](https://developer.mozilla.org/en-US/docs/WebAssembly). - -In this chapter we will discuss: - -1. [Using WebAssembly in Deno](./using_wasm.md) -2. [Using the Streaming WebAssembly APIs](./using_streaming_wasm.md) -3. [Helpful Resources](./wasm_resources.md) diff --git a/runtime/manual/runtime/webassembly/using_streaming_wasm.md b/runtime/manual/runtime/webassembly/using_streaming_wasm.md deleted file mode 100644 index 16a7445d4..000000000 --- a/runtime/manual/runtime/webassembly/using_streaming_wasm.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Using the Streaming WebAssembly APIs" ---- - -The -[most efficient](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming) -way to fetch, compile and instantiate a WebAssembly module is to use the -streaming variants of the WebAssembly API. For example, you can use -`instantiateStreaming` combined with `fetch` to perform all three steps in one -go: - -```ts -const { instance, module } = await WebAssembly.instantiateStreaming( - fetch("https://wpt.live/wasm/incrementer.wasm"), -); - -const increment = instance.exports.increment as (input: number) => number; -console.log(increment(41)); -``` - -Note that the `.wasm` file must be served with the `application/wasm` MIME type. -If you want to do additional work on the module before instantiation you can -instead use `compileStreaming`: - -```ts -const module = await WebAssembly.compileStreaming( - fetch("https://wpt.live/wasm/incrementer.wasm"), -); - -/* do some more stuff */ - -const instance = await WebAssembly.instantiate(module); -instance.exports.increment as (input: number) => number; -``` - -If for some reason you cannot make use of the streaming methods you can fall -back to the less efficient `compile` and `instantiate` methods. See for example -the -[MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate). -For a more in-depth look on what makes the streaming methods more performant, -see for example -[this post](https://hacks.mozilla.org/2018/01/making-webassembly-even-faster-firefoxs-new-streaming-and-tiering-compiler/). diff --git a/runtime/manual/runtime/webassembly/using_wasm.md b/runtime/manual/runtime/webassembly/using_wasm.md deleted file mode 100644 index dc0793cff..000000000 --- a/runtime/manual/runtime/webassembly/using_wasm.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Using WebAssembly in Deno" ---- - -To run WebAssembly in Deno, all you need is a binary to run. WebAssembly is a -binary data format. This means that `.wasm` files are not directly human -readable, and not intended to be written by hand. Instead a compiler for a -language like Rust, C++, or Go _emits_ `.wasm` files. - -The following binary exports a `main` function that just returns `42` upon -invocation: - -```ts -// deno-fmt-ignore -const wasmCode = new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, - 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, - 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, - 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, - 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, - 65, 42, 11 -]); - -const wasmModule = new WebAssembly.Module(wasmCode); - -const wasmInstance = new WebAssembly.Instance(wasmModule); - -const main = wasmInstance.exports.main as CallableFunction; -console.log(main().toString()); -``` - -As the code above shows, the following steps need to be performed in order to -load WebAssembly in a JavaScript program: - -1. Fetching the binary (usually in the form of a `.wasm` file, though we are - using a simple byte array for now) -2. Compiling the binary into a `WebAssembly.Module` object -3. Instantiating the WebAssembly module - -For more complex scenarios you will probably want to write in a programming -language that compiles down to WebAssembly instead of hand writing instructions. -A number of languages exist that can do this, such as -[Rust](https://www.rust-lang.org/), [Go](https://golang.org/) or -[AssemblyScript](https://www.assemblyscript.org/). As an example, a Rust program -that compiles to the aforementioned bytes would look something like this: - -```rust -pub fn main() -> u32 { // u32 stands for an unsigned integer using 32 bits of memory. - 42 -} -``` - -Aside from the methods shown in the preceding example, it is also possible to -use the streaming methods of the WebAssembly API, as will be shown on the next -page. diff --git a/runtime/manual/runtime/webassembly/wasm_resources.md b/runtime/manual/runtime/webassembly/wasm_resources.md deleted file mode 100644 index 90f0b0046..000000000 --- a/runtime/manual/runtime/webassembly/wasm_resources.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Helpful Resources" ---- - -This page contains some further information that is helpful when using and/or -developing WebAssembly modules. - -## WebAssembly API - -Further information on all parts of the WebAssembly API can be found on -[MDN](https://developer.mozilla.org/en-US/docs/WebAssembly). - -## Working with Non-Numeric Types - -The code samples in this chapter only used numeric types in the WebAssembly -modules. To run WebAssembly with more complex types (strings, classes) you will -want to use tools that generate type bindings between JavaScript and the -language used to compile to WebAssembly. - -An example on how to create type bindings between JavaScript and Rust, compiling -it into a binary and calling it from a JavaScript program can be found on -[MDN](https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm). - -If you plan to do a lot of work with Web APIs in Rust+WebAssembly, you may find -the [web_sys](https://rustwasm.github.io/wasm-bindgen/web-sys/index.html) and -[js_sys](https://rustwasm.github.io/wasm-bindgen/contributing/js-sys/index.html) -Rust crates useful. `web_sys` contains bindings to most of the Web APIs that are -available in Deno, while `js_sys` provides bindings to JavaScript's standard, -built-in objects. - -## Optimization - -For production builds it can be a good idea to perform optimizations on -WebAssembly binaries. If you're mainly serving binaries over networks then -optimizing for size can make a real difference, whereas if you're mainly -executing WebAssembly on a server to perform computationally intensive tasks, -optimizing for speed can be beneficial. You can find a good guide on optimizing -(production) builds -[here](https://rustwasm.github.io/docs/book/reference/code-size.html). In -addition, the -[rust-wasm group](https://rustwasm.github.io/docs/book/reference/tools.html) has -a list of tools that can be used to optimize and manipulate WebAssembly -binaries. diff --git a/runtime/manual/runtime/workers.md b/runtime/manual/runtime/workers.md deleted file mode 100644 index 4324c6d3a..000000000 --- a/runtime/manual/runtime/workers.md +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: "Workers" ---- - -Deno supports -[`Web Worker API`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker). - -Workers can be used to run code on multiple threads. Each instance of `Worker` -is run on a separate thread, dedicated only to that worker. - -Currently Deno supports only `module` type workers; thus it's essential to pass -the `type: "module"` option when creating a new worker. - -Use of relative module specifiers in the main worker are only supported with -`--location ` passed on the CLI. This is not recommended for portability. -You can instead use the `URL` constructor and `import.meta.url` to easily create -a specifier for some nearby script. Dedicated workers, however, have a location -and this capability by default. - -```ts -// Good -new Worker(import.meta.resolve("./worker.js"), { type: "module" }); - -// Bad -new Worker(import.meta.resolve("./worker.js")); -new Worker(import.meta.resolve("./worker.js"), { type: "classic" }); -new Worker("./worker.js", { type: "module" }); -``` - -As with regular modules, you can use top-level `await` in worker modules. -However, you should be careful to always register the message handler before the -first `await`, since messages can be lost otherwise. This is not a bug in Deno, -it's just an unfortunate interaction of features, and it also happens in all -browsers that support module workers. - -```ts -import { delay } from "jsr:@std/async@1/delay"; - -// First await: waits for a second, then continues running the module. -await delay(1000); - -// The message handler is only set after that 1s delay, so some of the messages -// that reached the worker during that second might have been fired when no -// handler was registered. -self.onmessage = (evt) => { - console.log(evt.data); -}; -``` - -## Instantiation permissions - -Creating a new `Worker` instance is similar to a dynamic import; therefore Deno -requires appropriate permission for this action. - -For workers using local modules; `--allow-read` permission is required: - -**main.ts** - -```ts -new Worker(import.meta.resolve("./worker.ts"), { type: "module" }); -``` - -**worker.ts** - -```ts -console.log("hello world"); -self.close(); -``` - -```shell -$ deno run main.ts -error: Uncaught PermissionDenied: read access to "./worker.ts", run again with the --allow-read flag - -$ deno run --allow-read main.ts -hello world -``` - -For workers using remote modules; `--allow-net` permission is required: - -**main.ts** - -```ts -new Worker("https://example.com/worker.ts", { type: "module" }); -``` - -**worker.ts** (at https://example.com/worker.ts) - -```ts -console.log("hello world"); -self.close(); -``` - -```shell -$ deno run main.ts -error: Uncaught PermissionDenied: net access to "https://example.com/worker.ts", run again with the --allow-net flag - -$ deno run --allow-net main.ts -hello world -``` - -## Using Deno in worker - -> Starting in v1.22 the `Deno` namespace is available in worker scope by -> default. To enable the namespace in earlier versions pass -> `deno: { namespace: true }` when creating a new worker. - -**main.js** - -```js -const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", -}); - -worker.postMessage({ filename: "./log.txt" }); -``` - -**worker.js** - -```js -self.onmessage = async (e) => { - const { filename } = e.data; - const text = await Deno.readTextFile(filename); - console.log(text); - self.close(); -}; -``` - -**log.txt** - -```console -hello world -``` - -```shell -$ deno run --allow-read main.js -hello world -``` - -> Starting in v1.23 `Deno.exit()` no longer exits the process with the provided -> exit code. Instead is an alias to `self.close()`, which causes only the worker -> to shutdown. This better aligns with the Web platform, as there is no way in -> the browser for a worker to close the page. - -## Specifying worker permissions - -> This is an unstable Deno feature. Learn more about -> [unstable features](/runtime/fundamentals/stability/). - -The permissions available for the worker are analogous to the CLI permission -flags, meaning every permission enabled there can be disabled at the level of -the Worker API. You can find a more detailed description of each of the -permission options [here](../basics/permissions.md). - -By default a worker will inherit permissions from the thread it was created in, -however in order to allow users to limit the access of this worker we provide -the `deno.permissions` option in the worker API. - -- For permissions that support granular access you can pass in a list of the - desired resources the worker will have access to, and for those who only have - the on/off option you can pass true/false respectively. - - ```ts - const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", - deno: { - permissions: { - net: [ - "deno.land", - ], - read: [ - new URL("./file_1.txt", import.meta.url), - new URL("./file_2.txt", import.meta.url), - ], - write: false, - }, - }, - }); - ``` - -- Granular access permissions receive both absolute and relative routes as - arguments, however take into account that relative routes will be resolved - relative to the file the worker is instantiated in, not the path the worker - file is currently in - - ```ts - const worker = new Worker( - new URL("./worker/worker.js", import.meta.url).href, - { - type: "module", - deno: { - permissions: { - read: [ - "/home/user/Documents/deno/worker/file_1.txt", - "./worker/file_2.txt", - ], - }, - }, - }, - ); - ``` - -- Both `deno.permissions` and its children support the option `"inherit"`, which - implies it will borrow its parent permissions. - - ```ts - // This worker will inherit its parent permissions - const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", - deno: { - permissions: "inherit", - }, - }); - ``` - - ```ts - // This worker will inherit only the net permissions of its parent - const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", - deno: { - permissions: { - env: false, - hrtime: false, - net: "inherit", - ffi: false, - read: false, - run: false, - write: false, - }, - }, - }); - ``` - -- Not specifying the `deno.permissions` option or one of its children will cause - the worker to inherit by default. - - ```ts - // This worker will inherit its parent permissions - const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", - }); - ``` - - ```ts - // This worker will inherit all the permissions of its parent BUT net - const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", - deno: { - permissions: { - net: false, - }, - }, - }); - ``` - -- You can disable the permissions of the worker all together by passing `"none"` - to the `deno.permissions` option. - - ```ts - // This worker will not have any permissions enabled - const worker = new Worker(import.meta.resolve("./worker.js"), { - type: "module", - deno: { - permissions: "none", - }, - }); - ``` diff --git a/runtime/reference/cli/run.md b/runtime/reference/cli/run.md index 450cb38bf..9db3a298f 100644 --- a/runtime/reference/cli/run.md +++ b/runtime/reference/cli/run.md @@ -24,9 +24,9 @@ deno run hello-world.ts By default, Deno runs programs in a sandbox without access to disk, network or ability to spawn subprocesses. This is because the Deno runtime is -[secure by default](/runtime/manual/runtime/permission_apis). You can grant or -deny required permissions using the -[`--allow-*` and `--deny-*` flags](/runtime/manual/basics/permissions). +[secure by default](/runtime/fundamentals/security/). You can grant or deny +required permissions using the +[`--allow-*` and `--deny-*` flags](/runtime/fundamentals/security/#permissions-list). ### Permissions examples diff --git a/runtime/reference/cli/unstable_flags.md b/runtime/reference/cli/unstable_flags.md index 3b4671c02..ecd17bfe5 100644 --- a/runtime/reference/cli/unstable_flags.md +++ b/runtime/reference/cli/unstable_flags.md @@ -216,7 +216,7 @@ Enabling this flag makes [Deno KV](/deploy/kv/manual) APIs available in the ## `--unstable-ffi` Enable unstable FFI APIs - -[learn more about FFI](/runtime/manual/runtime/ffi_api). +[learn more about FFI](/runtime/reference/deno_namespace_apis/#ffi). ## `--unstable-fs` diff --git a/runtime/reference/deno_namespace_apis.md b/runtime/reference/deno_namespace_apis.md new file mode 100644 index 000000000..826d9a673 --- /dev/null +++ b/runtime/reference/deno_namespace_apis.md @@ -0,0 +1,947 @@ +--- +title: "Deno Namespace APIs" +oldUrl: +- /runtime/manual/runtime/ +- /runtime/manual/runtime/builtin_apis/ +- /runtime/manual/runtime/permission_apis/ +- /runtime/manual/runtime/import_meta_api/ +- /runtime/manual/runtime/ffi_api/ +- /runtime/manual/runtime/program_lifecycle/ +--- + +The global `Deno` namespace contains APIs that are not web standard, including +APIs for reading from files, opening TCP sockets, serving HTTP, and executing +subprocesses, etc. + +For a full list of Deno Built-in APIs, see the [reference](/api/deno/~/Deno). +Below we highlight some of the most important. + +## File System + +The Deno runtime comes with +[various functions for working with files and directories](/api/deno/file-system). +You will need to use --allow-read and --allow-write permissions to gain access +to the file system. + +Refer to the links below for code examples of how to use the file system +functions. + +- [Reading files in several different ways](/examples/reading-files) +- [Reading files in streams](../../tutorials/file_server.md) +- [Reading a text file (`Deno.readTextFile`)](../../tutorials/read_write_files.md#reading-a-text-file) +- [Writing a text file (`Deno.writeTextFile`)](../../tutorials/read_write_files.md#writing-a-text-file) + +## Network + +The Deno runtime comes with +[built-in functions for dealing with connections to network ports](/api/deno/network). + +Refer to the links below for code examples for common functions. + +- [Connect to the hostname and port (`Deno.connect`)](/api/deno/~/Deno.connect) +- [Announcing on the local transport address (`Deno.listen`)](/api/deno/~/Deno.listen) + +## Subprocesses + +The Deno runtime comes with +[built-in functions for spinning up subprocesses](/api/deno/sub-process). + +Refer to the links below for code samples of how to create a subprocess. + +- [Creating a subprocess (`Deno.Command`)](/tutorials/subprocess/) + +## Errors + +The Deno runtime comes with [20 error classes](/api/deno/errors) that can be +raised in response to a number of conditions. + +Some examples are: + +```sh +Deno.errors.NotFound; +Deno.errors.WriteZero; +``` + +They can be used as below: + +```ts +try { + const file = await Deno.open("./some/file.txt"); +} catch (error) { + if (error instanceof Deno.errors.NotFound) { + console.error("the file was not found"); + } else { + // otherwise re-throw + throw error; + } +} +``` + +## HTTP Server + +Deno has two HTTP Server APIs: + +- [`Deno.serve`](/api/deno/~/Deno.serve): native, _higher-level_, supports + HTTP/1.1 and HTTP2, this is the preferred API to write HTTP servers in Deno. +- [`Deno.serveHttp`](/api/deno/~/Deno.serveHttp): native, _low-level_, supports + HTTP/1.1 and HTTP2. + +To start an HTTP server on a given port, use the `Deno.serve` function. This +function takes a handler function that will be called for each incoming request, +and is expected to return a response (or a promise resolving to a response). For +example: + +```ts +Deno.serve((_req) => { + return new Response("Hello, World!"); +}); +``` + +By default `Deno.serve` will listen on port `8000`, but this can be changed by +passing in a port number in options bag as the first or second argument. + +You can +[read more about how to use the HTTP server APIs](/runtime/fundamentals/http_server/). + +## Permissions + +Permissions are granted from the CLI when running the `deno` command. User code +will often assume its own set of required permissions, but there is no guarantee +during execution that the set of **granted** permissions will align with this. + +In some cases, ensuring a fault-tolerant program requires a way to interact with +the permission system at runtime. + +### Permission descriptors + +On the CLI, read permission for `/foo/bar` is represented as +`--allow-read=/foo/bar`. In runtime JS, it is represented as the following: + +```ts +const desc = { name: "read", path: "/foo/bar" } as const; +``` + +Other examples: + +```ts +// Global write permission. +const desc1 = { name: "write" } as const; + +// Write permission to `$PWD/foo/bar`. +const desc2 = { name: "write", path: "foo/bar" } as const; + +// Global net permission. +const desc3 = { name: "net" } as const; + +// Net permission to 127.0.0.1:8000. +const desc4 = { name: "net", host: "127.0.0.1:8000" } as const; + +// High-resolution time permission. +const desc5 = { name: "hrtime" } as const; +``` + +See [`PermissionDescriptor`](/api/deno/~/Deno.PermissionDescriptor) in API +reference for more details. Synchronous API counterparts (ex. +`Deno.permissions.querySync`) exist for all the APIs described below. + +### Query permissions + +Check, by descriptor, if a permission is granted or not. + +```ts +// deno run --allow-read=/foo main.ts + +const desc1 = { name: "read", path: "/foo" } as const; +console.log(await Deno.permissions.query(desc1)); +// PermissionStatus { state: "granted", partial: false } + +const desc2 = { name: "read", path: "/foo/bar" } as const; +console.log(await Deno.permissions.query(desc2)); +// PermissionStatus { state: "granted", partial: false } + +const desc3 = { name: "read", path: "/bar" } as const; +console.log(await Deno.permissions.query(desc3)); +// PermissionStatus { state: "prompt", partial: false } +``` + +If `--deny-read` flag was used to restrict some of the filepaths, the result +will contain `partial: true` describing that not all subpaths have permissions +granted: + +```ts +// deno run --allow-read=/foo --deny-read=/foo/bar main.ts + +const desc1 = { name: "read", path: "/foo" } as const; +console.log(await Deno.permissions.query(desc1)); +// PermissionStatus { state: "granted", partial: true } + +const desc2 = { name: "read", path: "/foo/bar" } as const; +console.log(await Deno.permissions.query(desc2)); +// PermissionStatus { state: "denied", partial: false } + +const desc3 = { name: "read", path: "/bar" } as const; +console.log(await Deno.permissions.query(desc3)); +// PermissionStatus { state: "prompt", partial: false } +``` + +### Permission states + +A permission state can be either "granted", "prompt" or "denied". Permissions +which have been granted from the CLI will query to `{ state: "granted" }`. Those +which have not been granted query to `{ state: "prompt" }` by default, while +`{ state: "denied" }` reserved for those which have been explicitly refused. +This will come up in [Request permissions](#request-permissions). + +### Permission strength + +The intuitive understanding behind the result of the second query in +[Query permissions](#query-permissions) is that read access was granted to +`/foo` and `/foo/bar` is within `/foo` so `/foo/bar` is allowed to be read. This +hold true, unless the CLI-granted permission is _partial_ to the queried +permissions (as an effect of using a `--deny-*` flag). + +We can also say that `desc1` is +_[stronger than](https://www.w3.org/TR/permissions/#ref-for-permissiondescriptor-stronger-than)_ +`desc2`. This means that for any set of CLI-granted permissions: + +1. If `desc1` queries to `{ state: "granted", partial: false }` then so must + `desc2`. +2. If `desc2` queries to `{ state: "denied", partial: false }` then so must + `desc1`. + +More examples: + +```ts +const desc1 = { name: "write" } as const; +// is stronger than +const desc2 = { name: "write", path: "/foo" } as const; + +const desc3 = { name: "net", host: "127.0.0.1" } as const; +// is stronger than +const desc4 = { name: "net", host: "127.0.0.1:8000" } as const; +``` + +### Request permissions + +Request an ungranted permission from the user via CLI prompt. + +```ts +// deno run main.ts + +const desc1 = { name: "read", path: "/foo" } as const; +const status1 = await Deno.permissions.request(desc1); +// ⚠️ Deno requests read access to "/foo". Grant? [y/n (y = yes allow, n = no deny)] y +console.log(status1); +// PermissionStatus { state: "granted", partial: false } + +const desc2 = { name: "read", path: "/bar" } as const; +const status2 = await Deno.permissions.request(desc2); +// ⚠️ Deno requests read access to "/bar". Grant? [y/n (y = yes allow, n = no deny)] n +console.log(status2); +// PermissionStatus { state: "denied", partial: false } +``` + +If the current permission state is "prompt", a prompt will appear on the user's +terminal asking them if they would like to grant the request. The request for +`desc1` was granted so its new status is returned and execution will continue as +if `--allow-read=/foo` was specified on the CLI. The request for `desc2` was +denied so its permission state is downgraded from "prompt" to "denied". + +If the current permission state is already either "granted" or "denied", the +request will behave like a query and just return the current status. This +prevents prompts both for already granted permissions and previously denied +requests. + +### Revoke permissions + +Downgrade a permission from "granted" to "prompt". + +```ts +// deno run --allow-read=/foo main.ts + +const desc = { name: "read", path: "/foo" } as const; +console.log(await Deno.permissions.revoke(desc)); +// PermissionStatus { state: "prompt", partial: false } +``` + +What happens when you try to revoke a permission which is _partial_ to one +granted on the CLI? + +```ts +// deno run --allow-read=/foo main.ts + +const desc = { name: "read", path: "/foo/bar" } as const; +console.log(await Deno.permissions.revoke(desc)); +// PermissionStatus { state: "prompt", partial: false } +const cliDesc = { name: "read", path: "/foo" } as const; +console.log(await Deno.permissions.revoke(cliDesc)); +// PermissionStatus { state: "prompt", partial: false } +``` + +The CLI-granted permission, which implies the revoked permission, was also +revoked. + +To understand this behavior, imagine that Deno stores an internal set of +_explicitly granted permission descriptors_. Specifying `--allow-read=/foo,/bar` +on the CLI initializes this set to: + +```ts +[ + { name: "read", path: "/foo" }, + { name: "read", path: "/bar" }, +]; +``` + +Granting a runtime request for `{ name: "write", path: "/foo" }` updates the set +to: + +```ts +[ + { name: "read", path: "/foo" }, + { name: "read", path: "/bar" }, + { name: "write", path: "/foo" }, +]; +``` + +Deno's permission revocation algorithm works by removing every element from this +set which is _stronger than_ the argument permission descriptor. + +Deno does not allow "fragmented" permission states, where some strong permission +is granted with exclusions of weak permissions implied by it. Such a system +would prove increasingly complex and unpredictable as you factor in a wider +variety of use cases and the `"denied"` state. This is a calculated trade-off of +granularity for security. + +## import.meta + +Deno supports a number of properties and methods on the +[`import.meta`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta) +API. It can be used to get information about the module, such as the module's +URL. + +### import.meta.url + +Returns the URL of the current module. + +```ts title="main.ts" +console.log(import.meta.url); +``` + +```sh +$ deno run main.ts +file:///dev/main.ts + +$ deno run https:/example.com/main.ts +https://example.com/main.ts +``` + +### import.meta.main + +Returns whether the current module is the entry point to your program. + +```ts title="main.ts" +import "./other.ts"; + +console.log(`Is ${import.meta.url} the main module?`, import.meta.main); +``` + +```ts title="other.ts" +console.log(`Is ${import.meta.url} the main module?`, import.meta.main); +``` + +```sh +$ deno run main.ts +Is file:///dev/other.ts the main module? false +Is file:///dev/main.ts the main module? true +``` + +### import.meta.filename + +_This property is only available for local modules (module that have +`file:///...` specifier) and returns `undefined` for remote modules._ + +Returns the fully resolved path to the current module. The value contains OS +specific path separators. + +```ts title="main.ts" +console.log(import.meta.filename); +``` + +On Unix: + +```sh +$ deno run main.ts +/dev/main.ts + +$ deno run https://example.com/main.ts +undefined +``` + +On Windows: + +```sh +$ deno run main.ts +C:\dev\main.ts + +$ deno run https://example.com/main.ts +undefined +``` + +### import.meta.dirname + +_This property is only available for local modules (module that have +`file:///...` specifier) and returns `undefined` for remote modules._ + +Returns the fully resolved path to the directory containing the current module. +The value contains OS specific path separators. + +```ts title="main.ts" +console.log(import.meta.dirname); +``` + +On Unix: + +```sh +$ deno run main.ts +/dev/ + +$ deno run https://example.com/main.ts +undefined +``` + +On Windows: + +```sh +$ deno run main.ts +C:\dev\ + +$ deno run https://example.com/main.ts +undefined +``` + +### import.meta.resolve + +Resolve specifiers relative to the current module. + +```ts +const worker = new Worker(import.meta.resolve("./worker.ts")); +``` + +The `import.meta.resolve` API takes into account the currently applied import +map, which gives you the ability to resolve "bare" specifiers as well. + +With such import map loaded... + +```json +{ + "imports": { + "fresh": "https://deno.land/x/fresh@1.0.1/dev.ts" + } +} +``` + +...you can now resolve: + +```js title="resolve.js" +console.log(import.meta.resolve("fresh")); +``` + +```sh +$ deno run resolve.js +https://deno.land/x/fresh@1.0.1/dev.ts +``` + +## FFI + +The FFI (foreign function interface) API allows users to call libraries written +in native languages that support the C ABIs (C/C++, Rust, Zig, V, etc.) using +`Deno.dlopen`. + +Here's an example showing how to call a Rust function from Deno: + +```rust +// add.rs +#[no_mangle] +pub extern "C" fn add(a: isize, b: isize) -> isize { + a + b +} +``` + +Compile it to a C dynamic library (`libadd.so` on Linux): + +```sh +rustc --crate-type cdylib add.rs +``` + +In C you can write it as: + +```c +// add.c +int add(int a, int b) { + return a + b; +} +``` + +And compile it: + +```sh +// unix +cc -c -o add.o add.c +cc -shared -W -o libadd.so add.o +// Windows +cl /LD add.c /link /EXPORT:add +``` + +Calling the library from Deno: + +```typescript +// ffi.ts + +// Determine library extension based on +// your OS. +let libSuffix = ""; +switch (Deno.build.os) { + case "windows": + libSuffix = "dll"; + break; + case "darwin": + libSuffix = "dylib"; + break; + default: + libSuffix = "so"; + break; +} + +const libName = `./libadd.${libSuffix}`; +// Open library and define exported symbols +const dylib = Deno.dlopen( + libName, + { + "add": { parameters: ["isize", "isize"], result: "isize" }, + } as const, +); + +// Call the symbol `add` +const result = dylib.symbols.add(35, 34); // 69 + +console.log(`Result from external addition of 35 and 34: ${result}`); +``` + +Run with `--allow-ffi` and `--unstable` flag: + +```sh +deno run --allow-ffi --unstable ffi.ts +``` + +### Non-blocking FFI + +There are many use cases where users might want to run CPU-bound FFI functions +in the background without blocking other tasks on the main thread. + +As of Deno 1.15, symbols can be marked `nonblocking` in `Deno.dlopen`. These +function calls will run on a dedicated blocking thread and will return a +`Promise` resolving to the desired `result`. + +Example of executing expensive FFI calls with Deno: + +```c +// sleep.c +#ifdef _WIN32 +#include +#else +#include +#endif + +int sleep(unsigned int ms) { + #ifdef _WIN32 + Sleep(ms); + #else + struct timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&ts, NULL); + #endif +} +``` + +Calling it from Deno: + +```typescript +// nonblocking_ffi.ts +const library = Deno.dlopen( + "./sleep.so", + { + sleep: { + parameters: ["usize"], + result: "void", + nonblocking: true, + }, + } as const, +); + +library.symbols.sleep(500).then(() => console.log("After")); +console.log("Before"); +``` + +Result: + +```sh +$ deno run --allow-ffi --unstable unblocking_ffi.ts +Before +After +``` + +### Callbacks + +Deno FFI API supports creating C callbacks from JavaScript functions for calling +back into Deno from dynamic libraries. An example of how callbacks are created +and used is as follows: + +```typescript +// callback_ffi.ts +const library = Deno.dlopen( + "./callback.so", + { + set_status_callback: { + parameters: ["function"], + result: "void", + }, + start_long_operation: { + parameters: [], + result: "void", + }, + check_status: { + parameters: [], + result: "void", + }, + } as const, +); + +const callback = new Deno.UnsafeCallback( + { + parameters: ["u8"], + result: "void", + } as const, + (success: number) => {}, +); + +// Pass the callback pointer to dynamic library +library.symbols.set_status_callback(callback.pointer); +// Start some long operation that does not block the thread +library.symbols.start_long_operation(); + +// Later, trigger the library to check if the operation is done. +// If it is, this call will trigger the callback. +library.symbols.check_status(); +``` + +If an `UnsafeCallback`'s callback function throws an error, the error will get +propagated up to the function that triggered the callback to be called (above, +that would be `check_status()`) and can be caught there. If a callback returning +a value throws then Deno will return 0 (null pointer for pointers) as the +result. + +`UnsafeCallback` is not deallocated by default as it can cause use-after-free +bugs. To properly dispose of an `UnsafeCallback` its `close()` method must be +called. + +```typescript +const callback = new Deno.UnsafeCallback( + { parameters: [], result: "void" } as const, + () => {}, +); + +// After callback is no longer needed +callback.close(); +// It is no longer safe to pass the callback as a parameter. +``` + +It is also possible for native libraries to setup interrupt handlers and to have +those directly trigger the callback. However, this is not recommended and may +cause unexpected side-effects and undefined behaviour. Preferably any interrupt +handlers would only set a flag that can later be polled similarly to how +`check_status()` is used above. + +### Supported types + +Here's a list of types supported currently by the Deno FFI API. + +| FFI Type | Deno | C | Rust | +| ---------------------- | -------------------- | ------------------------ | ------------------------- | +| `i8` | `number` | `char` / `signed char` | `i8` | +| `u8` | `number` | `unsigned char` | `u8` | +| `i16` | `number` | `short int` | `i16` | +| `u16` | `number` | `unsigned short int` | `u16` | +| `i32` | `number` | `int` / `signed int` | `i32` | +| `u32` | `number` | `unsigned int` | `u32` | +| `i64` | `number \| bigint` | `long long int` | `i64` | +| `u64` | `number \| bigint` | `unsigned long long int` | `u64` | +| `usize` | `number \| bigint` | `size_t` | `usize` | +| `isize` | `number \| bigint` | `size_t` | `isize` | +| `f32` | `number \| bigint` | `float` | `f32` | +| `f64` | `number \| bigint` | `double` | `f64` | +| `void`[1] | `undefined` | `void` | `()` | +| `pointer` | `{} \| null` | `void *` | `*mut c_void` | +| `buffer`[2] | `TypedArray \| null` | `uint8_t *` | `*mut u8` | +| `function`[3] | `{} \| null` | `void (*fun)()` | `Option` | +| `{ struct: [...] }`[4] | `TypedArray` | `struct MyStruct` | `MyStruct` | + +As of Deno 1.25, the `pointer` type has been split into a `pointer` and a +`buffer` type to ensure users take advantage of optimizations for Typed Arrays, +and as of Deno 1.31 the JavaScript representation of `pointer` has become an +opaque pointer object or `null` for null pointers. + +- [1] `void` type can only be used as a result type. +- [2] `buffer` type accepts TypedArrays as parameter, but it always returns a + pointer object or `null` when used as result type like the `pointer` type. +- [3] `function` type works exactly the same as the `pointer` type as a + parameter and result type. +- [4] `struct` type is for passing and returning C structs by value (copy). The + `struct` array must enumerate each of the struct's fields' type in order. The + structs are padded automatically: Packed structs can be defined by using an + appropriate amount of `u8` fields to avoid padding. Only TypedArrays are + supported as structs, and structs are always returned as `Uint8Array`s. + +### deno_bindgen + +[`deno_bindgen`](https://github.com/denoland/deno_bindgen) is the official tool +to simplify glue code generation of Deno FFI libraries written in Rust. + +It is similar to [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) in +the Rust WASM ecosystem. + +Here's an example showing its usage: + +```rust +// mul.rs +use deno_bindgen::deno_bindgen; + +#[deno_bindgen] +struct Input { + a: i32, + b: i32, +} + +#[deno_bindgen] +fn mul(input: Input) -> i32 { + input.a * input.b +} +``` + +Run `deno_bindgen` to generate bindings. You can now directly import them into +Deno: + +```ts +// mul.ts +import { mul } from "./bindings/bindings.ts"; +mul({ a: 10, b: 2 }); // 20 +``` + +Any issues related to `deno_bindgen` should be reported at +https://github.com/denoland/deno_bindgen/issues + +## Program Lifecycle + +Deno supports browser compatible lifecycle events: + +- [`load`](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event#:~:text=The%20load%20event%20is%20fired,for%20resources%20to%20finish%20loading.): + fired when the whole page has loaded, including all dependent resources such + as stylesheets and images. +- [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event#:~:text=The%20beforeunload%20event%20is%20fired,want%20to%20leave%20the%20page.): + fired when the event loop has no more work to do and is about to exit. + Scheduling more asynchronous work (like timers or network requests) will cause + the program to continue. +- [`unload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event): + fired when the document or a child resource is being unloaded. +- [`unhandledrejection`](https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event): + fired when a promise that has no rejection handler is rejected, ie. a promise + that has no `.catch()` handler or a second argument to `.then()`. +- [`rejectionhandled`](https://developer.mozilla.org/en-US/docs/Web/API/Window/rejectionhandled_event): + fired when a `.catch()` handler is added to a a promise that has already + rejected. This event is fired only if there's `unhandledrejection` listener + installed that prevents propagation of the event (which would result in the + program terminating with an error). + +You can use these events to provide setup and cleanup code in your program. + +Listeners for `load` events can be asynchronous and will be awaited, this event +cannot be canceled. Listeners for `beforeunload` need to be synchronous and can +be cancelled to keep the program running. Listeners for `unload` events need to +be synchronous and cannot be cancelled. + +**main.ts** + +```ts title="main.ts" +import "./imported.ts"; + +const handler = (e: Event): void => { + console.log(`got ${e.type} event in event handler (main)`); +}; + +globalThis.addEventListener("load", handler); + +globalThis.addEventListener("beforeunload", handler); + +globalThis.addEventListener("unload", handler); + +globalThis.onload = (e: Event): void => { + console.log(`got ${e.type} event in onload function (main)`); +}; + +globalThis.onbeforeunload = (e: Event): void => { + console.log(`got ${e.type} event in onbeforeunload function (main)`); +}; + +globalThis.onunload = (e: Event): void => { + console.log(`got ${e.type} event in onunload function (main)`); +}; + +console.log("log from main script"); +``` + +```ts title="imported.ts" +const handler = (e: Event): void => { + console.log(`got ${e.type} event in event handler (imported)`); +}; + +globalThis.addEventListener("load", handler); +globalThis.addEventListener("beforeunload", handler); +globalThis.addEventListener("unload", handler); + +globalThis.onload = (e: Event): void => { + console.log(`got ${e.type} event in onload function (imported)`); +}; + +globalThis.onbeforeunload = (e: Event): void => { + console.log(`got ${e.type} event in onbeforeunload function (imported)`); +}; + +globalThis.onunload = (e: Event): void => { + console.log(`got ${e.type} event in onunload function (imported)`); +}; + +console.log("log from imported script"); +``` + +A couple notes on this example: + +- `addEventListener` and `onload`/`onunload` are prefixed with `globalThis`, but + you could also use `self` or no prefix at all. + [It is not recommended to use `window` as a prefix](https://lint.deno.land/#no-window-prefix). +- You can use `addEventListener` and/or `onload`/`onunload` to define handlers + for events. There is a major difference between them, let's run the example: + +```shell +$ deno run main.ts +log from imported script +log from main script +got load event in event handler (imported) +got load event in event handler (main) +got load event in onload function (main) +got onbeforeunload event in event handler (imported) +got onbeforeunload event in event handler (main) +got onbeforeunload event in onbeforeunload function (main) +got unload event in event handler (imported) +got unload event in event handler (main) +got unload event in onunload function (main) +``` + +All listeners added using `addEventListener` were run, but `onload`, +`onbeforeunload` and `onunload` defined in `main.ts` overrode handlers defined +in `imported.ts`. + +In other words, you can use `addEventListener` to register multiple `"load"` or +`"unload"` event handlers, but only the last defined `onload`, `onbeforeunload`, +`onunload` event handlers will be executed. It is preferable to use +`addEventListener` when possible for this reason. + +### beforeunload + +```js +// beforeunload.js +let count = 0; + +console.log(count); + +globalThis.addEventListener("beforeunload", (e) => { + console.log("About to exit..."); + if (count < 4) { + e.preventDefault(); + console.log("Scheduling more work..."); + setTimeout(() => { + console.log(count); + }, 100); + } + + count++; +}); + +globalThis.addEventListener("unload", (e) => { + console.log("Exiting"); +}); + +count++; +console.log(count); + +setTimeout(() => { + count++; + console.log(count); +}, 100); +``` + +Running this program will print: + +```sh +$ deno run beforeunload.js +0 +1 +2 +About to exit... +Scheduling more work... +3 +About to exit... +Scheduling more work... +4 +About to exit... +Exiting +``` + +This has allowed us to polyfill `process.on("beforeExit")` in the Node +compatibility layer. + +### unhandledrejection event + +This event is fired when a promise that has no rejection handler is rejected, +ie. a promise that has no .catch() handler or a second argument to .then(). + +```js +// unhandledrejection.js +globalThis.addEventListener("unhandledrejection", (e) => { + console.log("unhandled rejection at:", e.promise, "reason:", e.reason); + e.preventDefault(); +}); + +function Foo() { + this.bar = Promise.reject(new Error("bar not available")); +} + +new Foo(); +Promise.reject(); +``` + +Running this program will print: + +```sh +$ deno run unhandledrejection.js +unhandled rejection at: Promise { + Error: bar not available + at new Foo (file:///dev/unhandled_rejection.js:7:29) + at file:///dev/unhandled_rejection.js:10:1 +} reason: Error: bar not available + at new Foo (file:///dev/unhandled_rejection.js:7:29) + at file:///dev/unhandled_rejection.js:10:1 +unhandled rejection at: Promise { undefined } reason: undefined +``` + +This API will allow us to polyfill `process.on("unhandledRejection")` in the +Node compatibility layer in future releases. diff --git a/runtime/reference/wasm.md b/runtime/reference/wasm.md new file mode 100644 index 000000000..4a712c23b --- /dev/null +++ b/runtime/reference/wasm.md @@ -0,0 +1,136 @@ +--- +title: "WebAssembly" +oldUrl: + - /runtime/manual/getting_started/webassembly/ + - /runtime/manual/runtime/webassembly/ + - /runtime/manual/runtime/webassembly/using_wasm/ + - /runtime/manual/runtime/webassembly/using_streaming_wasm/ + - /runtime/manual/runtime/webassembly/wasm_resources/ +--- + +Designed to be used alongside JavaScript to speed up key application components, +[WebAssembly](https://webassembly.org/) (WASM) can have much higher, and more +consistent execution speed than JavaScript - similar to C, C++, or Rust. Deno +can execute WebAssembly modules with the same interfaces that +[browsers provide](https://developer.mozilla.org/en-US/docs/WebAssembly). + +## Using WebAssembly in Deno + +To run WebAssembly in Deno, all you need is a binary to run. The following +binary exports a `main` function that just returns `42` upon invocation: + +```ts +// deno-fmt-ignore +const wasmCode = new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, + 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, + 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, + 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, + 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, + 65, 42, 11 +]); + +const wasmModule = new WebAssembly.Module(wasmCode); + +const wasmInstance = new WebAssembly.Instance(wasmModule); + +const main = wasmInstance.exports.main as CallableFunction; +console.log(main().toString()); +``` + +In order to load WebAssembly in a JavaScript program, the following steps need +to be performed: + +1. Fetching the binary (usually in the form of a `.wasm` file, though we are + using a simple byte array for now) +2. Compiling the binary into a `WebAssembly.Module` object +3. Instantiating the WebAssembly module + +WebAssembly is a binary data format, not intended to be human readable, nor to +be written by hand. Your wasm files should be generated by a compiler for a +language such as [Rust](https://www.rust-lang.org/), [Go](https://golang.org/) +or [AssemblyScript](https://www.assemblyscript.org/). + +As an example, a Rust program that compiles to the aforementioned bytes would +look something like this: + +```rust +pub fn main() -> u32 { // u32 stands for an unsigned integer using 32 bits of memory. + 42 +} +``` + +## Using the Streaming WebAssembly APIs + +The [most efficient](/api/web/~/WebAssembly.instantiateStreaming) way to fetch, +compile and instantiate a WebAssembly module is to use the streaming variants of +the WebAssembly API. For example, you can use `instantiateStreaming` combined +with `fetch` to perform all three steps in one go: + +```ts +const { instance, module } = await WebAssembly.instantiateStreaming( + fetch("https://wpt.live/wasm/incrementer.wasm"), +); + +const increment = instance.exports.increment as (input: number) => number; +console.log(increment(41)); +``` + +Note that the `.wasm` file must be served with the `application/wasm` MIME type. +If you want to do additional work on the module before instantiation you can +instead use [`compileStreaming`](/api/web/~/WebAssembly.compileStreaming): + +```ts +const module = await WebAssembly.compileStreaming( + fetch("https://wpt.live/wasm/incrementer.wasm"), +); + +/* do some more stuff */ + +const instance = await WebAssembly.instantiate(module); +instance.exports.increment as (input: number) => number; +``` + +If for some reason you cannot make use of the streaming methods you can fall +back to the less efficient [`compile`](/api/web/~/WebAssembly.compile) and +[`instantiate`](/api/web/~/WebAssembly.instantiate) methods. + +For a more in-depth look on what makes the streaming methods more performant, +[check out this post](https://hacks.mozilla.org/2018/01/making-webassembly-even-faster-firefoxs-new-streaming-and-tiering-compiler/). + +## WebAssembly API + +Further information on all parts of the WebAssembly API can be found on in the +[Deno Reference Guide](/api/web/~/WebAssembly) and on +[MDN](https://developer.mozilla.org/en-US/docs/WebAssembly). + +## Working with Non-Numeric Types + +The code samples in this document only used numeric types in the WebAssembly +modules. To run WebAssembly with more complex types (such as strings or classes) +you will need to use tools that generate type bindings between JavaScript and +the language used to compile to WebAssembly. + +An example on how to create type bindings between JavaScript and Rust, compiling +it into a binary and calling it from a JavaScript program can be found on +[MDN](https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm). + +If you plan to do a lot of work with Web APIs in Rust+WebAssembly, you may find +the [web_sys](https://rustwasm.github.io/wasm-bindgen/web-sys/index.html) and +[js_sys](https://rustwasm.github.io/wasm-bindgen/contributing/js-sys/index.html) +Rust crates useful. `web_sys` contains bindings to most of the Web APIs that are +available in Deno, while `js_sys` provides bindings to JavaScript's standard, +built-in objects. + +## Optimization + +For production builds you can perform optimizations on WebAssembly binaries. If +you're serving binaries over a network then optimizing for size can make a real +difference. If you're mainly executing WebAssembly on a server to perform +computationally intensive tasks, optimizing for speed can be beneficial. You can +find a good guide on optimizing (production) builds +[here](https://rustwasm.github.io/docs/book/reference/code-size.html). In +addition, the +[rust-wasm group](https://rustwasm.github.io/docs/book/reference/tools.html) has +a list of tools that can be used to optimize and manipulate WebAssembly +binaries. diff --git a/runtime/reference/web_platform_apis.md b/runtime/reference/web_platform_apis.md new file mode 100644 index 000000000..19ce51902 --- /dev/null +++ b/runtime/reference/web_platform_apis.md @@ -0,0 +1,499 @@ +--- +title: "Using Web Platform APIs" +oldUrl: + - /runtime/manual/runtime/navigator_api/ + - /runtime/manual/runtime/web_platform_apis/ + - /runtime/manual/runtime/location_api/ + - /runtime/manual/runtime/web_storage_api/ +--- + +One way Deno simplifies web and cloud development is by using Web Platform APIs +(like `fetch`) over proprietary APIs. This means if you've ever built for the +browser, you're likely already familiar with Deno, and if you're learning Deno, +you're also investing in your knowledge of the web. + +Check out the [reference guide for Deno's supported Web APIs](/api/web/). To +check if a Web Platform API is available in Deno, you can click on +[the interface on MDN](https://developer.mozilla.org/en-US/docs/Web/API#interfaces) +and refer to +[its Browser Compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/AbortController#browser_compatibility). + +## fetch + +The [`fetch`](/api/web/~/fetch) API can be used to make HTTP requests. It is +implemented as specified in the +[WHATWG `fetch` spec](https://fetch.spec.whatwg.org/). + +### Spec deviations + +- The Deno user agent does not have a cookie jar. As such, the `set-cookie` + header on a response is not processed, or filtered from the visible response + headers. +- Deno does not follow the same-origin policy, because the Deno user agent + currently does not have the concept of origins, and it does not have a cookie + jar. This means Deno does not need to protect against leaking authenticated + data cross origin. Because of this Deno does not implement the following + sections of the WHATWG `fetch` specification: + - Section `3.1. 'Origin' header`. + - Section `3.2. CORS protocol`. + - Section `3.5. CORB`. + - Section `3.6. 'Cross-Origin-Resource-Policy' header`. + - `Atomic HTTP redirect handling`. + - The `opaqueredirect` response type. +- A `fetch` with a `redirect` mode of `manual` will return a `basic` response + rather than an `opaqueredirect` response. +- The specification is vague on how + [`file:` URLs are to be handled](https://fetch.spec.whatwg.org/#scheme-fetch). + Firefox is the only mainstream browser that implements fetching `file:` URLs, + and even then it doesn't work by default. As of Deno 1.16, Deno supports + fetching local files. See the next section for details. +- The `request` and `response` header guards are implemented, but unlike + browsers do not have any constraints on which header names are allowed. +- The `referrer`, `referrerPolicy`, `mode`, `credentials`, `cache`, `integrity`, + `keepalive`, and `window` properties and their relevant behaviours in + `RequestInit` are not implemented. The relevant fields are not present on the + `Request` object. +- Request body upload streaming is supported (on HTTP/1.1 and HTTP/2). Unlike + the current fetch proposal, the implementation supports duplex streaming. +- The `set-cookie` header is not concatenated when iterated over in the + `headers` iterator. This behaviour is in the + [process of being specified](https://github.com/whatwg/fetch/pull/1346). + +### Fetching local files + +Deno supports fetching `file:` URLs. This makes it easier to write code that +uses the same code path on a server as local, as well as easier to author code +that works both with the Deno CLI and Deno Deploy. + +Deno only supports absolute file URLs, this means that `fetch("./some.json")` +will not work. It should be noted though that if +[`--location`](./location_api.md) is specified, relative URLs use the +`--location` as the base, but a `file:` URL cannot be passed as the +`--location`. + +To be able to fetch a resource, relative to the current module, which would work +if the module is local or remote, you should to use `import.meta.url` as the +base. For example: + +```js +const response = await fetch(new URL("./config.json", import.meta.url)); +const config = await response.json(); +``` + +Notes on fetching local files: + +- Permissions are applied to reading resources, so an appropriate `--allow-read` + permission is needed to be able to read a local file. +- Fetching locally only supports the `GET` method, and will reject the promise + with any other method. +- A file that does not exist simply rejects the promise with a vague + `TypeError`. This is to avoid the potential of fingerprinting attacks. +- No headers are set on the response. Therefore it is up to the consumer to + determine things like the content type or content length. +- Response bodies are streamed from the Rust side, so large files are available + in chunks, and can be cancelled. + +## CustomEvent and EventTarget + +The [DOM Event API](/api/web/~/Event) can be used to dispatch and listen to +events happening in an application. It is implemented as specified in the +[WHATWG DOM spec](https://dom.spec.whatwg.org/#events). + +### Spec deviations + +- Events do not bubble, because Deno does not have a DOM hierarchy, so there is + no tree for Events to bubble/capture through. +- `timeStamp` property is always set to `0`. + +## Typings + +The TypeScript definitions for the implemented web APIs can be found in the +[`lib.deno.shared_globals.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.shared_globals.d.ts) +and +[`lib.deno.window.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.window.d.ts) +files. + +Definitions that are specific to workers can be found in the +[`lib.deno.worker.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.worker.d.ts) +file. + +## Location + +Deno supports the [`location`](/api/web/~/Location) global from the web. + +### Location flag + +There is no "web page" whose URL we can use for a location in a Deno process. We +instead allow users to emulate a document location by specifying one on the CLI +using the `--location` flag. It can be a `http` or `https` URL. + +```ts +// deno run --location https://example.com/path main.ts + +console.log(location.href); +// "https://example.com/path" +``` + +You must pass `--location ` for this to work. If you don't, any access to +the `location` global will throw an error. + +```ts +// deno run main.ts + +console.log(location.href); +// error: Uncaught ReferenceError: Access to "location", run again with --location . +``` + +Setting `location` or any of its fields will normally cause navigation in +browsers. This is not applicable in Deno, so it will throw in this situation. + +```ts +// deno run --location https://example.com/path main.ts + +location.pathname = "./foo"; +// error: Uncaught NotSupportedError: Cannot set "location.pathname". +``` + +### Extended usage + +On the web, resource resolution (excluding modules) typically uses the value of +`location.href` as the root on which to base any relative URLs. This affects +some web APIs adopted by Deno. + +#### Fetch API + +```ts +// deno run --location https://api.github.com/ --allow-net main.ts + +const response = await fetch("./orgs/denoland"); +// Fetches "https://api.github.com/orgs/denoland". +``` + +The `fetch()` call above would throw if the `--location` flag was not passed, +since there is no web-analogous location to base it onto. + +#### Worker modules + +```ts +// deno run --location https://example.com/index.html --allow-net main.ts + +const worker = new Worker("./workers/hello.ts", { type: "module" }); +// Fetches worker module at "https://example.com/workers/hello.ts". +``` + +:::note + +For the above use cases, it is preferable to pass URLs in full rather than +relying on `--location`. You can manually base a relative URL using the `URL` +constructor if needed. + +::: + +The `--location` flag is intended for those who have a specific purpose in mind +for emulating a document location and are aware that this will only work at +application-level. However, you may also use it to silence errors from a +dependency which is frivolously accessing the `location` global. + +## Web Storage + +The [Web Storage API](/api/web/storage) provides an API for storing string keys +and values. Persisting data works similar to a browser, and has a 10MB storage +limit. The global `sessionStorage` object only persists data for the current +execution context, while `localStorage` persists data from execution to +execution. + +In a browser, `localStorage` persists data uniquely per origin (effectively the +protocol plus hostname plus port). As of Deno 1.16, Deno has a set of rules to +determine what is a unique storage location: + +- When using the `--location` flag, the origin for the location is used to + uniquely store the data. That means a location of `http://example.com/a.ts` + and `http://example.com/b.ts` and `http://example.com:80/` would all share the + same storage, but `https://example.com/` would be different. +- If there is no location specifier, but there is a `--config` configuration + file specified, the absolute path to that configuration file is used. That + means `deno run --config deno.jsonc a.ts` and + `deno run --config deno.jsonc b.ts` would share the same storage, but + `deno run --config tsconfig.json a.ts` would be different. +- If there is no configuration or location specifier, Deno uses the absolute + path to the main module to determine what storage is shared. The Deno REPL + generates a "synthetic" main module that is based off the current working + directory where `deno` is started from. This means that multiple invocations + of the REPL from the same path will share the persisted `localStorage` data. + +To set, get and remove items from `localStorage`, you can use the following: + +```ts +// Set an item in localStorage +localStorage.setItem("myDemo", "Deno App"); + +// Read an item from localStorage +const cat = localStorage.getItem("myDemo"); + +// Remove an item from localStorage +localStorage.removeItem("myDemo"); + +// Remove all items from localStorage +localStorage.clear(); +``` + +## Web Workers + +Deno supports the [`Web Worker API`](/api/web/workers). + +Workers can be used to run code on multiple threads. Each instance of `Worker` +is run on a separate thread, dedicated only to that worker. + +Currently Deno supports only `module` type workers; thus it's essential to pass +the `type: "module"` option when creating a new worker. + +Use of relative module specifiers in the main worker are only supported with +`--location ` passed on the CLI. This is not recommended for portability. +You can instead use the `URL` constructor and `import.meta.url` to easily create +a specifier for some nearby script. Dedicated workers, however, have a location +and this capability by default. + +```ts +// Good +new Worker(import.meta.resolve("./worker.js"), { type: "module" }); + +// Bad +new Worker(import.meta.resolve("./worker.js")); +new Worker(import.meta.resolve("./worker.js"), { type: "classic" }); +new Worker("./worker.js", { type: "module" }); +``` + +As with regular modules, you can use top-level `await` in worker modules. +However, you should be careful to always register the message handler before the +first `await`, since messages can be lost otherwise. This is not a bug in Deno, +it's just an unfortunate interaction of features, and it also happens in all +browsers that support module workers. + +```ts +import { delay } from "jsr:@std/async@1/delay"; + +// First await: waits for a second, then continues running the module. +await delay(1000); + +// The message handler is only set after that 1s delay, so some of the messages +// that reached the worker during that second might have been fired when no +// handler was registered. +self.onmessage = (evt) => { + console.log(evt.data); +}; +``` + +### Instantiation permissions + +Creating a new `Worker` instance is similar to a dynamic import; therefore Deno +requires appropriate permission for this action. + +For workers using local modules; `--allow-read` permission is required: + +```ts title="main.ts" +new Worker(import.meta.resolve("./worker.ts"), { type: "module" }); +``` + +```ts title="worker.ts" +console.log("hello world"); +self.close(); +``` + +```shell +$ deno run main.ts +error: Uncaught PermissionDenied: read access to "./worker.ts", run again with the --allow-read flag + +$ deno run --allow-read main.ts +hello world +``` + +For workers using remote modules; `--allow-net` permission is required: + +```ts title="main.ts" +new Worker("https://example.com/worker.ts", { type: "module" }); +``` + +```ts title="worker.ts" +// This file is hosted at https://example.com/worker.ts +console.log("hello world"); +self.close(); +``` + +```shell +$ deno run main.ts +error: Uncaught PermissionDenied: net access to "https://example.com/worker.ts", run again with the --allow-net flag + +$ deno run --allow-net main.ts +hello world +``` + +### Using Deno in a worker + +```js title="main.js" +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", +}); + +worker.postMessage({ filename: "./log.txt" }); +``` + +```js title="worker.js" +self.onmessage = async (e) => { + const { filename } = e.data; + const text = await Deno.readTextFile(filename); + console.log(text); + self.close(); +}; +``` + +```text title="log.txt" +hello world +``` + +```shell +$ deno run --allow-read main.js +hello world +``` + +### Specifying worker permissions + +:::warning This is an unstable Deno feature. Learn more about +[unstable features](/runtime/fundamentals/stability/). ::: + +The permissions available for the worker are analogous to the CLI permission +flags, meaning every permission enabled there can be disabled at the level of +the Worker API. You can find a more detailed description of each of the +permission options [here](../basics/permissions.md). + +By default a worker will inherit permissions from the thread it was created in, +however in order to allow users to limit the access of this worker we provide +the `deno.permissions` option in the worker API. + +For permissions that support granular access you can pass in a list of the +desired resources the worker will have access to, and for those who only have +the on/off option you can pass true/false respectively: + +```ts +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", + deno: { + permissions: { + net: [ + "deno.land", + ], + read: [ + new URL("./file_1.txt", import.meta.url), + new URL("./file_2.txt", import.meta.url), + ], + write: false, + }, + }, +}); +``` + +Granular access permissions receive both absolute and relative routes as +arguments, however take into account that relative routes will be resolved +relative to the file the worker is instantiated in, not the path the worker file +is currently in: + +```ts +const worker = new Worker( + new URL("./worker/worker.js", import.meta.url).href, + { + type: "module", + deno: { + permissions: { + read: [ + "/home/user/Documents/deno/worker/file_1.txt", + "./worker/file_2.txt", + ], + }, + }, + }, +); +``` + +Both `deno.permissions` and its children support the option `"inherit"`, which +implies it will borrow its parent permissions: + +```ts +// This worker will inherit its parent permissions +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", + deno: { + permissions: "inherit", + }, +}); +``` + +```ts +// This worker will inherit only the net permissions of its parent +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", + deno: { + permissions: { + env: false, + hrtime: false, + net: "inherit", + ffi: false, + read: false, + run: false, + write: false, + }, + }, +}); +``` + +Not specifying the `deno.permissions` option or one of its children will cause +the worker to inherit by default: + +```ts +// This worker will inherit its parent permissions +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", +}); +``` + +```ts +// This worker will inherit all the permissions of its parent BUT net +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", + deno: { + permissions: { + net: false, + }, + }, +}); +``` + +You can disable the permissions of the worker all together by passing `"none"` +to the `deno.permissions` option: + +```ts +// This worker will not have any permissions enabled +const worker = new Worker(import.meta.resolve("./worker.js"), { + type: "module", + deno: { + permissions: "none", + }, +}); +``` + +## Deviations of other APIs from spec + +### Cache API + +Only the following APIs are implemented: + +- [CacheStorage::open()](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/open) +- [CacheStorage::has()](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/has) +- [CacheStorage::delete()](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage/delete) +- [Cache::match()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match) +- [Cache::put()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/put) +- [Cache::delete()](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete) + +A few things that are different compared to browsers: + +1. You cannot pass relative paths to the APIs. The request can be an instance of + Request or URL or a url string. +2. `match()` & `delete()` don't support query options yet. From f64e4c2f472735237c6c8e2bcb2aae5cbf291a87 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 08:37:27 +0200 Subject: [PATCH 03/12] fix: redirects --- runtime/reference/cli/benchmarker.md | 2 +- runtime/reference/cli/cache.md | 2 +- runtime/reference/cli/check.md | 2 +- runtime/reference/cli/compiler.md | 2 +- runtime/reference/cli/completions.md | 2 +- runtime/reference/cli/coverage.md | 2 +- runtime/reference/cli/dependency_inspector.md | 2 +- runtime/reference/cli/documentation_generator.md | 2 +- runtime/reference/cli/eval.md | 2 +- runtime/reference/cli/formatter.md | 2 +- runtime/reference/cli/init.md | 2 +- runtime/reference/cli/jupyter.md | 2 +- runtime/reference/cli/linter.md | 2 +- runtime/reference/cli/lsp.md | 2 +- runtime/reference/cli/publish.md | 2 +- runtime/reference/cli/repl.md | 2 +- runtime/reference/cli/run.md | 2 +- runtime/reference/cli/script_installer.md | 2 +- runtime/reference/cli/serve.md | 2 +- runtime/reference/cli/task_runner.md | 2 +- runtime/reference/cli/test.md | 2 +- runtime/reference/cli/types.md | 2 +- runtime/reference/cli/uninstall.md | 2 +- runtime/reference/cli/unstable_flags.md | 2 +- runtime/reference/cli/upgrade.md | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/runtime/reference/cli/benchmarker.md b/runtime/reference/cli/benchmarker.md index c575230e3..0a8ac35c7 100644 --- a/runtime/reference/cli/benchmarker.md +++ b/runtime/reference/cli/benchmarker.md @@ -1,6 +1,6 @@ --- title: "`deno bench`, benchmarking tool" -oldUrl: /runtime/reference/cli/benchmarker/ +oldUrl: /runtime/manual/tools/benchmarker/ --- Deno has a built-in benchmark runner that you can use for checking performance diff --git a/runtime/reference/cli/cache.md b/runtime/reference/cli/cache.md index 1fa760f26..85732d06b 100644 --- a/runtime/reference/cli/cache.md +++ b/runtime/reference/cli/cache.md @@ -1,6 +1,6 @@ --- title: "deno cache" -oldUrl: /runtime/reference/cli/cache/ +oldUrl: /runtime/manual/tools/cache/ --- Cache and compile remote dependencies recursively. diff --git a/runtime/reference/cli/check.md b/runtime/reference/cli/check.md index 3b9c6fe67..f8ed183cc 100644 --- a/runtime/reference/cli/check.md +++ b/runtime/reference/cli/check.md @@ -1,6 +1,6 @@ --- title: "deno check" -oldUrl: /runtime/reference/cli/check/ +oldUrl: /runtime/manual/tools/check/ --- Type-check a program without execution. diff --git a/runtime/reference/cli/compiler.md b/runtime/reference/cli/compiler.md index ed9b75244..058dd5e48 100644 --- a/runtime/reference/cli/compiler.md +++ b/runtime/reference/cli/compiler.md @@ -1,6 +1,6 @@ --- title: "`deno compile`, standalone executables" -oldUrl: /runtime/reference/cli/compiler/ +oldUrl: /runtime/manual/tools/compiler/ --- `deno compile [--output ] ` will compile the script into a diff --git a/runtime/reference/cli/completions.md b/runtime/reference/cli/completions.md index 1e4bfbef0..427a76ce6 100644 --- a/runtime/reference/cli/completions.md +++ b/runtime/reference/cli/completions.md @@ -1,6 +1,6 @@ --- title: "deno completions" -oldUrl: /runtime/reference/cli/completions/ +oldUrl: /runtime/manual/tools/completions/ --- Output shell completion script to standard output. diff --git a/runtime/reference/cli/coverage.md b/runtime/reference/cli/coverage.md index 40e4691bd..c0dc6a7b2 100644 --- a/runtime/reference/cli/coverage.md +++ b/runtime/reference/cli/coverage.md @@ -1,6 +1,6 @@ --- title: "deno coverage" -oldUrl: /runtime/reference/cli/coverage/ +oldUrl: /runtime/manual/tools/coverage/ --- Print coverage reports from coverage profiles. diff --git a/runtime/reference/cli/dependency_inspector.md b/runtime/reference/cli/dependency_inspector.md index eabde9833..ce4a7c282 100644 --- a/runtime/reference/cli/dependency_inspector.md +++ b/runtime/reference/cli/dependency_inspector.md @@ -1,6 +1,6 @@ --- title: "`deno info`, dependency inspector" -oldUrl: /runtime/reference/cli/dependency_inspector/ +oldUrl: /runtime/manual/tools/dependency_inspector/ --- `deno info [URL]` will inspect an ES module and all of its dependencies. diff --git a/runtime/reference/cli/documentation_generator.md b/runtime/reference/cli/documentation_generator.md index cf5958ad5..6ee329b69 100644 --- a/runtime/reference/cli/documentation_generator.md +++ b/runtime/reference/cli/documentation_generator.md @@ -1,6 +1,6 @@ --- title: "`deno doc`, documentation generator" -oldUrl: /runtime/reference/cli/documentation_generator/ +oldUrl: /runtime/manual/tools/documentation_generator/ --- `deno doc` followed by a list of one or more source files will print the JSDoc diff --git a/runtime/reference/cli/eval.md b/runtime/reference/cli/eval.md index 1e0049e5d..8dfb8d7f0 100644 --- a/runtime/reference/cli/eval.md +++ b/runtime/reference/cli/eval.md @@ -1,6 +1,6 @@ --- title: "deno eval" -oldUrl: /runtime/reference/cli/eval/ +oldUrl: /runtime/manual/tools/eval/ --- Evaluate JavaScript from the command line. diff --git a/runtime/reference/cli/formatter.md b/runtime/reference/cli/formatter.md index b34be0f1d..d87175895 100644 --- a/runtime/reference/cli/formatter.md +++ b/runtime/reference/cli/formatter.md @@ -2,7 +2,7 @@ title: "`deno fmt`, code formatting" oldUrl: - /runtime/tools/formatter/ - - /runtime/reference/cli/formatter/ + - /runtime/manual/tools/formatter/ --- Deno ships with a built-in code formatter that will auto-format the following diff --git a/runtime/reference/cli/init.md b/runtime/reference/cli/init.md index cf1999605..84e67cc6c 100644 --- a/runtime/reference/cli/init.md +++ b/runtime/reference/cli/init.md @@ -1,6 +1,6 @@ --- title: "`deno init`, start a new project" -oldUrl: /runtime/reference/cli/init/ +oldUrl: /runtime/manual/tools/init/ --- Starting a new project with Deno has always been incredibly simple: you just diff --git a/runtime/reference/cli/jupyter.md b/runtime/reference/cli/jupyter.md index cbd5d49d6..a878a1ebc 100644 --- a/runtime/reference/cli/jupyter.md +++ b/runtime/reference/cli/jupyter.md @@ -1,6 +1,6 @@ --- title: "Jupyter Kernel for Deno" -oldUrl: /runtime/reference/cli/jupyter/ +oldUrl: /runtime/manual/tools/jupyter/ --- Deno ships with a built-in Jupyter kernel that allows you to write JavaScript diff --git a/runtime/reference/cli/linter.md b/runtime/reference/cli/linter.md index a9cd801b3..56a3e6a71 100644 --- a/runtime/reference/cli/linter.md +++ b/runtime/reference/cli/linter.md @@ -3,7 +3,7 @@ title: "`deno lint`, linter" oldUrl: - /runtime/tools/linter/ - /runtime/fundamentals/linting_and_formatting/lint-cli-ref - - /runtime/reference/cli/linter/ + - /runtime/manual/tools/linter/ --- Deno ships with a built-in code linter for JavaScript and TypeScript. diff --git a/runtime/reference/cli/lsp.md b/runtime/reference/cli/lsp.md index fbdcff9ee..646ad916a 100644 --- a/runtime/reference/cli/lsp.md +++ b/runtime/reference/cli/lsp.md @@ -1,6 +1,6 @@ --- title: "deno lsp" -oldUrl: /runtime/reference/cli/lsp/ +oldUrl: /runtime/manual/tools/lsp/ --- :::info diff --git a/runtime/reference/cli/publish.md b/runtime/reference/cli/publish.md index 39dac21f8..14d076edd 100644 --- a/runtime/reference/cli/publish.md +++ b/runtime/reference/cli/publish.md @@ -1,6 +1,6 @@ --- title: "deno publish" -oldUrl: /runtime/reference/cli/publish/ +oldUrl: /runtime/manual/tools/publish/ --- _This applies to `deno` v1.42.0. and above._ diff --git a/runtime/reference/cli/repl.md b/runtime/reference/cli/repl.md index ca35d9fdb..badf2f2f4 100644 --- a/runtime/reference/cli/repl.md +++ b/runtime/reference/cli/repl.md @@ -1,6 +1,6 @@ --- title: "`deno repl`, interactive scripting prompt" -oldUrl: /runtime/reference/cli/repl/ +oldUrl: /runtime/manual/tools/repl/ --- `deno repl` starts a read-eval-print-loop, which lets you interactively build up diff --git a/runtime/reference/cli/run.md b/runtime/reference/cli/run.md index 9db3a298f..c7d47a064 100644 --- a/runtime/reference/cli/run.md +++ b/runtime/reference/cli/run.md @@ -1,6 +1,6 @@ --- title: "`deno run`, run a file" -oldUrl: /runtime/reference/cli/run/ +oldUrl: /runtime/manual/tools/run/ --- `deno run [OPTIONS] [SCRIPT_ARG]` run a JavaScript or TypeScript file. diff --git a/runtime/reference/cli/script_installer.md b/runtime/reference/cli/script_installer.md index 33c963b47..7a38b1151 100644 --- a/runtime/reference/cli/script_installer.md +++ b/runtime/reference/cli/script_installer.md @@ -1,6 +1,6 @@ --- title: "`deno install`, script installer" -oldUrl: /runtime/reference/cli/script_installer/ +oldUrl: /runtime/manual/tools/script_installer/ --- diff --git a/runtime/reference/cli/serve.md b/runtime/reference/cli/serve.md index a91ccb13d..ab3e5e8f0 100644 --- a/runtime/reference/cli/serve.md +++ b/runtime/reference/cli/serve.md @@ -1,6 +1,6 @@ --- title: "deno serve" -oldUrl: /runtime/reference/cli/serve/ +oldUrl: /runtime/manual/tools/serve/ --- In addition to `deno run`, Deno offers a `deno serve` command-line option that diff --git a/runtime/reference/cli/task_runner.md b/runtime/reference/cli/task_runner.md index 3efdcd1cd..79b3c9015 100644 --- a/runtime/reference/cli/task_runner.md +++ b/runtime/reference/cli/task_runner.md @@ -2,7 +2,7 @@ title: "`deno task`" oldUrl: - /runtime/tools/task_runner/ - - /runtime/reference/cli/task_runner/ + - /runtime/manual/tools/task_runner/ --- `deno task` provides a cross-platform way to define and execute custom commands diff --git a/runtime/reference/cli/test.md b/runtime/reference/cli/test.md index 6b159bd3a..e92b863e3 100644 --- a/runtime/reference/cli/test.md +++ b/runtime/reference/cli/test.md @@ -1,6 +1,6 @@ --- title: "deno test" -oldUrl: /runtime/reference/cli/test/ +oldUrl: /runtime/manual/tools/test/ --- Run tests using Deno's built-in test runner. diff --git a/runtime/reference/cli/types.md b/runtime/reference/cli/types.md index effc7734d..e5d3b9aee 100644 --- a/runtime/reference/cli/types.md +++ b/runtime/reference/cli/types.md @@ -1,6 +1,6 @@ --- title: "deno types" -oldUrl: /runtime/reference/cli/types/ +oldUrl: /runtime/manual/tools/types/ --- Prints runtime TypeScript declarations. diff --git a/runtime/reference/cli/uninstall.md b/runtime/reference/cli/uninstall.md index eeb471a9c..85611ba4c 100644 --- a/runtime/reference/cli/uninstall.md +++ b/runtime/reference/cli/uninstall.md @@ -1,6 +1,6 @@ --- title: "deno uninstall" -oldUrl: /runtime/reference/cli/uninstall/ +oldUrl: /runtime/manual/tools/uninstall/ --- Uninstalls an executable script in the installation root's bin directory. diff --git a/runtime/reference/cli/unstable_flags.md b/runtime/reference/cli/unstable_flags.md index ecd17bfe5..c999bf1f0 100644 --- a/runtime/reference/cli/unstable_flags.md +++ b/runtime/reference/cli/unstable_flags.md @@ -2,7 +2,7 @@ title: "Unstable Feature Flags" oldUrl: - /runtime/tools/unstable_flags/ - - /runtime/reference/cli/unstable_flags/ + - /runtime/manual/tools/unstable_flags/ --- New features of the Deno runtime are often released behind feature flags, so diff --git a/runtime/reference/cli/upgrade.md b/runtime/reference/cli/upgrade.md index d8fe1a9f0..44c5583f8 100644 --- a/runtime/reference/cli/upgrade.md +++ b/runtime/reference/cli/upgrade.md @@ -1,6 +1,6 @@ --- title: "deno upgrade" -oldUrl: /runtime/reference/cli/upgrade/ +oldUrl: /runtime/manual/tools/upgrade/ --- Upgrade deno executable to the given version. From 5561dfee5154b9e1fa9871f5bccd99daf84f56e3 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 08:39:24 +0200 Subject: [PATCH 04/12] fix: add redirect --- runtime/reference/web_platform_apis.md | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/reference/web_platform_apis.md b/runtime/reference/web_platform_apis.md index 19ce51902..c77988e61 100644 --- a/runtime/reference/web_platform_apis.md +++ b/runtime/reference/web_platform_apis.md @@ -5,6 +5,7 @@ oldUrl: - /runtime/manual/runtime/web_platform_apis/ - /runtime/manual/runtime/location_api/ - /runtime/manual/runtime/web_storage_api/ + - /runtime/manual/runtime/workers/ --- One way Deno simplifies web and cloud development is by using Web Platform APIs From fecf12bffb0061455cf5f19d27b5034f5911dd6c Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 13:51:49 +0200 Subject: [PATCH 05/12] fix: use official HTTP/2 name --- runtime/fundamentals/http_server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/fundamentals/http_server.md b/runtime/fundamentals/http_server.md index b55eef132..72f276761 100644 --- a/runtime/fundamentals/http_server.md +++ b/runtime/fundamentals/http_server.md @@ -6,7 +6,7 @@ oldUrl: Deno has a built in HTTP server API that allows you to write HTTP servers. The [`Deno.serve`](https://docs.deno.com/api/deno/~/Deno.serve) API supports -HTTP/1.1 and HTTP2. +HTTP/1.1 and HTTP/2. ## A "Hello World" server From 50fd0adeacc90ba37a8e1fd9aec29f0c5bc677b1 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 14:07:48 +0200 Subject: [PATCH 06/12] doc: use shorter sidebar label --- runtime/_data.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runtime/_data.ts b/runtime/_data.ts index 8a0ef3a43..082778f67 100644 --- a/runtime/_data.ts +++ b/runtime/_data.ts @@ -29,7 +29,10 @@ export const sidebar = [ "/runtime/fundamentals/debugging/", "/runtime/fundamentals/workspaces/", "/runtime/fundamentals/linting_and_formatting/", - "/runtime/fundamentals/http_server/", + { + label: "HTTP Server", + id: "/runtime/fundamentals/http_server/", + }, "/runtime/fundamentals/installation/", "/runtime/fundamentals/stability/", ], From 460beb4117efe59310ea11a2a42ed5f9bf19bea1 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 14:07:59 +0200 Subject: [PATCH 07/12] fix: admonition styling --- runtime/fundamentals/http_server.md | 48 ++++++++++++++++++----------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/runtime/fundamentals/http_server.md b/runtime/fundamentals/http_server.md index 72f276761..580b94c7b 100644 --- a/runtime/fundamentals/http_server.md +++ b/runtime/fundamentals/http_server.md @@ -66,11 +66,15 @@ Deno.serve(async (req) => { }); ``` -> ⚠️ Be aware that the `req.text()` call can fail if the user hangs up the -> connection before the body is fully received. Make sure to handle this case. -> Do note this can happen in all methods that read from the request body, such -> as `req.json()`, `req.formData()`, `req.arrayBuffer()`, -> `req.body.getReader().read()`, `req.body.pipeTo()`, etc. +:::caution + +Be aware that the `req.text()` call can fail if the user hangs up the connection +before the body is fully received. Make sure to handle this case. Do note this +can happen in all methods that read from the request body, such as `req.json()`, +`req.formData()`, `req.arrayBuffer()`, `req.body.getReader().read()`, +`req.body.pipeTo()`, etc. + +::: ## Responding with a response @@ -117,11 +121,15 @@ Deno.serve((req) => { }); ``` -ℹNote the `cancel` function above. This is called when the client hangs up the +:::note + +Note the `cancel` function above. This is called when the client hangs up the connection. It is important to make sure that you handle this case, as otherwise the server will keep queuing up messages forever, and eventually run out of memory. +::: + Be aware that the response body stream is "cancelled" when the client hangs up the connection. Make sure to handle this case. This can surface itself as an error in a `write()` call on a `WritableStream` object that is attached to the @@ -129,13 +137,6 @@ response body `ReadableStream` object (for example through a `TransformStream`). ## HTTPS support -:::note - -To use HTTPS, you will need a valid TLS certificate and a private key for your -server. - -::: - To use HTTPS, pass two extra arguments in the options bag: `cert` and `key`. These are contents of the certificate and key files, respectively. @@ -147,6 +148,13 @@ Deno.serve({ }, handler); ``` +:::note + +To use HTTPS, you will need a valid TLS certificate and a private key for your +server. + +::: + ## HTTP/2 support HTTP/2 support is "automatic" when using the HTTP server APIs with Deno. You @@ -179,9 +187,9 @@ compressed if the following conditions are true: [in the code](https://github.com/denoland/deno/blob/v1.21.0/ext/http/compressible.rs).) - The response body is greater than 64 bytes. -When the response body is compressed, Deno will set the Content-Encoding header -to reflect the encoding, as well as ensure the Vary header is adjusted or added -to indicate which request headers affected the response. +When the response body is compressed, Deno will set the `Content-Encoding` +header to reflect the encoding, as well as ensure the `Vary` header is adjusted +or added to indicate which request headers affected the response. In addition to the logic above, there are a few reasons why a response **won’t** be compressed automatically: @@ -208,7 +216,7 @@ handling, and so on. However, if you are interested creating your own robust and performant web servers in Deno, lower-level, _native_ HTTP server APIs are available. -:::warning +:::caution You should probably not be using the `Deno.serveHTTP` API, as it is not easy to get right. Use the `Deno.serve` API instead. @@ -225,11 +233,15 @@ network port. To do this in Deno, you use const server = Deno.listen({ port: 8080 }); ``` -ℹWhen supplying a port, Deno assumes you are going to listen on a TCP socket as +:::info + +When supplying a port, Deno assumes you are going to listen on a TCP socket as well as bind to the localhost. You can specify `transport: "tcp"` to be more explicit as well as provide an IP address or hostname in the `hostname` property as well. +::: + If there is an issue with opening the network port, `Deno.listen()` will throw, so often in a server sense, you will want to wrap it in a `try ... catch` block in order to handle exceptions, such as the port already being in use. From e520b495fb007dc2e818840200951618d012cf35 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 14:36:22 +0200 Subject: [PATCH 08/12] docs: extract `Deno.listen` from http server doc --- runtime/_data.ts | 1 + runtime/fundamentals/http_server.md | 264 ----------------------- runtime/reference/tcp_udp_connections.md | 98 +++++++++ 3 files changed, 99 insertions(+), 264 deletions(-) create mode 100644 runtime/reference/tcp_udp_connections.md diff --git a/runtime/_data.ts b/runtime/_data.ts index 082778f67..2740dd547 100644 --- a/runtime/_data.ts +++ b/runtime/_data.ts @@ -145,6 +145,7 @@ export const sidebar = [ "/runtime/reference/deno_namespace_apis/", "/runtime/reference/web_platform_apis/", "/runtime/reference/wasm/", + "/runtime/reference/tcp_udp_connections/", ], }, { diff --git a/runtime/fundamentals/http_server.md b/runtime/fundamentals/http_server.md index 580b94c7b..f0732d821 100644 --- a/runtime/fundamentals/http_server.md +++ b/runtime/fundamentals/http_server.md @@ -208,270 +208,6 @@ be compressed automatically: value. This indicates that your server doesn’t want Deno or any downstream proxies to modify the response. -## Deno.serveHttp - -We recommend that you use the `Deno.serve` API described above, as it handles -all of the intricacies of parallel requests on a single connection, error -handling, and so on. However, if you are interested creating your own robust and -performant web servers in Deno, lower-level, _native_ HTTP server APIs are -available. - -:::caution - -You should probably not be using the `Deno.serveHTTP` API, as it is not easy to -get right. Use the `Deno.serve` API instead. - -::: - -## Listening for a connection - -In order to accept requests, first you need to listen for a connection on a -network port. To do this in Deno, you use -[`Deno.listen()`](/api/deno/~/Deno.listen): - -```ts -const server = Deno.listen({ port: 8080 }); -``` - -:::info - -When supplying a port, Deno assumes you are going to listen on a TCP socket as -well as bind to the localhost. You can specify `transport: "tcp"` to be more -explicit as well as provide an IP address or hostname in the `hostname` property -as well. - -::: - -If there is an issue with opening the network port, `Deno.listen()` will throw, -so often in a server sense, you will want to wrap it in a `try ... catch` block -in order to handle exceptions, such as the port already being in use. - -You can also listen for a TLS connection (e.g. HTTPS) using `Deno.listenTls()`: - -```ts -const server = Deno.listenTls({ - port: 8443, - certFile: "localhost.crt", - keyFile: "localhost.key", - alpnProtocols: ["h2", "http/1.1"], -}); -``` - -The `certFile` and `keyFile` options are required and point to the appropriate -certificate and key files for the server. They are relative to the CWD for Deno. -The `alpnProtocols` property is optional, but if you want to be able to support -HTTP/2 on the server, you add the protocols here, as the protocol negotiation -happens during the TLS negotiation with the client and server. - -## Handling connections - -Once we are listening for a connection, we need to handle the connection. The -return value of `Deno.listen()` or `Deno.listenTls()` is a `Deno.Listener` which -is an async iterable which yields up `Deno.Conn` connections as well as provide -a couple methods for handling connections. - -To use it as an async iterable you would do something like this: - -```ts -const server = Deno.listen({ port: 8080 }); - -for await (const conn of server) { - // ...handle the connection... -} -``` - -Every connection made would yield a `Deno.Conn` assigned to `conn`. Then further -processing can be applied to the connection. - -There is also an `.accept()` method on the listener which can be used: - -```ts -const server = Deno.listen({ port: 8080 }); - -while (true) { - try { - const conn = await server.accept(); - // ... handle the connection ... - } catch (err) { - // The listener has closed - break; - } -} -``` - -Whether using the async iterator or the `.accept()` method, exceptions can be -thrown and robust production code should handle these using `try ... catch` -blocks. When it comes to accepting TLS connections, there can be many -conditions, like invalid or unknown certificates which can be surfaced on the -listener and might need handling in the user code. - -A listener also has a `.close()` method which can be used to close the listener. - -## Serving HTTP - -Once a connection is accepted, you can use `Deno.serveHttp()` to handle HTTP -requests and responses on the connection. `Deno.serveHttp()` returns a -`Deno.HttpConn`. A `Deno.HttpConn` is like a `Deno.Listener` in that requests -the connection receives from the client are asynchronously yielded up as a -`Deno.RequestEvent`. - -To deal with HTTP requests as async iterable it would look something like this: - -```ts -const server = Deno.listen({ port: 8080 }); - -for await (const conn of server) { - (async () => { - const httpConn = Deno.serveHttp(conn); - for await (const requestEvent of httpConn) { - // ... handle requestEvent ... - } - })(); -} -``` - -The `Deno.HttpConn` also has the method `.nextRequest()` which can be used to -await the next request. It would look something like this: - -```ts -const server = Deno.listen({ port: 8080 }); - -while (true) { - try { - const conn = await server.accept(); - (async () => { - const httpConn = Deno.serveHttp(conn); - while (true) { - try { - const requestEvent = await httpConn.nextRequest(); - // ... handle requestEvent ... - } catch (err) { - // the connection has finished - break; - } - } - })(); - } catch (err) { - // The listener has closed - break; - } -} -``` - -Note that in both cases we are using an IIFE to create an inner function to deal -with each connection. If we awaited the HTTP requests in the same function scope -as the one we were receiving the connections, we would be blocking accepting -additional connections, which would make it seem that our server was "frozen". -In practice, it might make more sense to have a separate function all together: - -```ts -async function handle(conn: Deno.Conn) { - const httpConn = Deno.serveHttp(conn); - for await (const requestEvent of httpConn) { - // ... handle requestEvent - } -} - -const server = Deno.listen({ port: 8080 }); - -for await (const conn of server) { - handle(conn); -} -``` - -In the examples from this point on, we will focus on what would occur within an -example `handle()` function and remove the listening and connection -"boilerplate". - -### HTTP Requests and Responses - -HTTP requests and responses in Deno are essentially the inverse of web standard -[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). The -Deno HTTP Server API and the Fetch API leverage the -[`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and -[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object -classes. So if you are familiar with the Fetch API you just need to flip them -around in your mind and now it is a server API. - -As mentioned above, a `Deno.HttpConn` asynchronously yields up -`Deno.RequestEvent`s. These request events contain a `.request` property and a -`.respondWith()` method. - -The `.request` property is an instance of the `Request` class with the -information about the request. For example, if we wanted to know what URL path -was being requested, we would do something like this: - -```ts -async function handle(conn: Deno.Conn) { - const httpConn = Deno.serveHttp(conn); - for await (const requestEvent of httpConn) { - const url = new URL(requestEvent.request.url); - console.log(`path: ${url.pathname}`); - } -} -``` - -The `.respondWith()` method is how we complete a request. The method takes -either a `Response` object or a `Promise` which resolves with a `Response` -object. Responding with a basic "hello world" would look like this: - -```ts -async function handle(conn: Deno.Conn) { - const httpConn = Deno.serveHttp(conn); - for await (const requestEvent of httpConn) { - await requestEvent.respondWith( - new Response("hello world", { - status: 200, - }), - ); - } -} -``` - -Note that we awaited the `.respondWith()` method. It isn't required, but in -practice any errors in processing the response will cause the promise returned -from the method to be rejected, like if the client disconnected before all the -response could be sent. While there may not be anything your application needs -to do, not handling the rejection will cause an "unhandled rejection" to occur -which will terminate the Deno process, which isn't so good for a server. In -addition, you might want to await the promise returned in order to determine -when to do any cleanup from for the request/response cycle. - -The web standard `Response` object is pretty powerful, allowing easy creation of -complex and rich responses to a client, and Deno strives to provide a `Response` -object that as closely matches the web standard as possible, so if you are -wondering how to send a particular response, checkout the documentation for the -web standard -[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response). - -## HTTP/2 Support - -HTTP/2 support is effectively transparent within the Deno runtime. Typically -HTTP/2 is negotiated between a client and a server during the TLS connection -setup via -[ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation). To -enable this, you need to provide the protocols you want to support when you -start listening via the `alpnProtocols` property. This will enable the -negotiation to occur when the connection is made. For example: - -```ts -const server = Deno.listenTls({ - port: 8443, - certFile: "localhost.crt", - keyFile: "localhost.key", - alpnProtocols: ["h2", "http/1.1"], -}); -``` - -The protocols are provided in order of preference. In practice, the only two -protocols that are supported currently are HTTP/2 and HTTP/1.1 which are -expressed as `h2` and `http/1.1`. - -Currently Deno does not support upgrading a plain-text HTTP/1.1 connection to an -HTTP/2 cleartext connection via the `Upgrade` header (see: -[#10275](https://github.com/denoland/deno/issues/10275)), so therefore HTTP/2 -support is only available via a TLS/HTTPS connection. - ## Serving WebSockets Deno can upgrade incoming HTTP requests to a WebSocket. This allows you to diff --git a/runtime/reference/tcp_udp_connections.md b/runtime/reference/tcp_udp_connections.md new file mode 100644 index 000000000..1eedf023c --- /dev/null +++ b/runtime/reference/tcp_udp_connections.md @@ -0,0 +1,98 @@ +--- +title: "TCP & UDP connections" +--- + +The [`Deno.listen`](/api/deno/~/Deno.listen)-API gives you low level access to +handling TCP or UDP connections. If your use case is spinning up an HTTP server +you should use [`Deno.serve`](/runtime/fundamentals/http_server) instead. + +## Listening for a connection + +In order to accept requests, first you need to listen for a connection on a +network port. + +```ts +const listener = Deno.listen({ port: 8080 }); +``` + +:::info + +When supplying a port, Deno assumes you are going to listen on a TCP socket as +well as bind to the localhost. You can specify `transport: "tcp"` to be more +explicit as well as provide an IP address or hostname in the `hostname` property +as well. + +::: + +If there is an issue with opening the network port, `Deno.listen()` will throw, +so often in a server sense, you will want to wrap it in a `try ... catch` block +in order to handle exceptions, such as the port already being in use. + +```ts +try { + const listener = Deno.listen({ port: 8080 }); +} catch (err) { + // handle error +} +``` + +You can also listen for a TLS connection (e.g. HTTPS) using `Deno.listenTls()`: + +```ts +const server = Deno.listenTls({ + port: 8443, + certFile: "localhost.crt", + keyFile: "localhost.key", + alpnProtocols: ["h2", "http/1.1"], +}); +``` + +The `certFile` and `keyFile` options are required and point to the appropriate +certificate and key files for the server. They are relative to the CWD for Deno. +The `alpnProtocols` property is optional, but if you want to be able to support +HTTP/2 on the server, you add the protocols here, as the protocol negotiation +happens during the TLS negotiation with the client and server. + +## Handling connections + +Once we are listening for a connection, we need to handle the connection. The +return value of `Deno.listen()` or `Deno.listenTls()` is a `Deno.Listener` which +is an async iterable which yields up `Deno.Conn` connections as well as provide +a couple methods for handling connections. + +To use it as an async iterable you would do something like this: + +```ts +const server = Deno.listen({ port: 8080 }); + +for await (const conn of server) { + // ...handle the connection... +} +``` + +Every connection made would yield a `Deno.Conn` assigned to `conn`. Then further +processing can be applied to the connection. + +There is also an `.accept()` method on the listener which can be used: + +```ts +const server = Deno.listen({ port: 8080 }); + +while (true) { + try { + const conn = await server.accept(); + // ... handle the connection ... + } catch (err) { + // The listener has closed + break; + } +} +``` + +Whether using the async iterator or the `.accept()` method, exceptions can be +thrown and robust production code should handle these using `try ... catch` +blocks. When it comes to accepting TLS connections, there can be many +conditions, like invalid or unknown certificates which can be surfaced on the +listener and might need handling in the user code. + +A listener also has a `.close()` method which can be used to close the listener. From 18826a1becef850ead341c991a54a32304e5f793 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 14:42:16 +0200 Subject: [PATCH 09/12] docs: update websocket section --- runtime/fundamentals/http_server.md | 50 ++++++++++++----------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/runtime/fundamentals/http_server.md b/runtime/fundamentals/http_server.md index f0732d821..719e53c81 100644 --- a/runtime/fundamentals/http_server.md +++ b/runtime/fundamentals/http_server.md @@ -216,45 +216,37 @@ handle WebSocket endpoints on your HTTP servers. To upgrade an incoming `Request` to a WebSocket you use the `Deno.upgradeWebSocket` function. This returns an object consisting of a `Response` and a web standard `WebSocket` object. The returned response should -be used to respond to the incoming request using the `respondWith` method. Only -once `respondWith` is called with the returned response, the WebSocket is -activated and can be used. +be used to respond to the incoming request. Because the WebSocket protocol is symmetrical, the `WebSocket` object is identical to the one that can be used for client side communication. Documentation for it can be found [on MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket). -> Note: We are aware that this API can be challenging to use, and are planning -> to switch to -> [`WebSocketStream`](https://github.com/ricea/websocketstream-explainer/blob/master/README.md) -> once it is stabilized and ready for use. - ```ts -async function handle(conn: Deno.Conn) { - const httpConn = Deno.serveHttp(conn); - for await (const requestEvent of httpConn) { - await requestEvent.respondWith(handleReq(requestEvent.request)); +Deno.serve((req) => { + if (req.headers.get("upgrade") != "websocket") { + return new Response(null, { status: 501 }); } -} -function handleReq(req: Request): Response { - const upgrade = req.headers.get("upgrade") || ""; - if (upgrade.toLowerCase() != "websocket") { - return new Response("request isn't trying to upgrade to websocket."); - } const { socket, response } = Deno.upgradeWebSocket(req); - socket.onopen = () => console.log("socket opened"); - socket.onmessage = (e) => { - console.log("socket message:", e.data); - socket.send(new Date().toString()); - }; - socket.onerror = (e) => console.log("socket errored:", e); - socket.onclose = () => console.log("socket closed"); + socket.addEventListener("open", () => { + console.log("a client connected!"); + }); + + socket.addEventListener("message", (event) => { + if (event.data === "ping") { + socket.send("pong"); + } + }); + return response; -} +}); ``` -WebSockets are only supported on HTTP/1.1 for now. The connection the WebSocket -was created on can not be used for HTTP traffic after a WebSocket upgrade has -been performed. +:::note + +The connection the WebSocket was created on can not be used for HTTP traffic +after a WebSocket upgrade has been performed. + +::: From a42399d32657927ac166e651e2b25ce377e016eb Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 14:46:09 +0200 Subject: [PATCH 10/12] docs: add back websocket http note --- runtime/fundamentals/http_server.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runtime/fundamentals/http_server.md b/runtime/fundamentals/http_server.md index 719e53c81..d8f13321a 100644 --- a/runtime/fundamentals/http_server.md +++ b/runtime/fundamentals/http_server.md @@ -250,3 +250,9 @@ The connection the WebSocket was created on can not be used for HTTP traffic after a WebSocket upgrade has been performed. ::: + +:::note + +Note that WebSockets are only supported on HTTP/1.1 for now. + +::: From adb7ba066c555a8e1e2af98adb39f88862550153 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Sep 2024 14:49:26 +0200 Subject: [PATCH 11/12] chore: update signature --- runtime/fundamentals/http_server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/fundamentals/http_server.md b/runtime/fundamentals/http_server.md index d8f13321a..0e6979321 100644 --- a/runtime/fundamentals/http_server.md +++ b/runtime/fundamentals/http_server.md @@ -35,7 +35,7 @@ passing in a port number in options bag as the first or second argument: Deno.serve({ port: 4242 }, handler); // To listen on port 4242 and bind to 0.0.0.0. -Deno.serve({ port: 4242, hostname: "0.0.0.0", handler }); +Deno.serve({ port: 4242, hostname: "0.0.0.0" }, handler); ``` ## Inspecting the incoming request From 0fbdd32523d80920c1513f561bc569da6917f599 Mon Sep 17 00:00:00 2001 From: Jo Franchetti Date: Tue, 3 Sep 2024 15:03:57 +0100 Subject: [PATCH 12/12] redirect tools --- runtime/getting_started/command_line_interface.md | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/getting_started/command_line_interface.md b/runtime/getting_started/command_line_interface.md index 64a5dc038..b8aa5bc02 100644 --- a/runtime/getting_started/command_line_interface.md +++ b/runtime/getting_started/command_line_interface.md @@ -4,6 +4,7 @@ oldUrl: - /manual/getting_started/command_line_interface - /runtime/manual/getting_started/command_line_interface/ - /runtime/fundamentals/command_line_interface/ + - /runtime/manual/tools/ --- Deno is a command line program. The Deno command line interface (CLI) can be