Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions api_links_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { walk } from "@std/fs";
import { assert } from "@std/assert";

const DIRS_TO_CHECK = ["./runtime"];

/**
* Find unlinked `Deno.*` API references in markdown prose.
*
* Matches: `Deno.serve` `Deno.readFile()` `Deno.FsFile`
* Ignores: [`Deno.serve`](/api/deno/~/Deno.serve) (already linked)
* Ignores: references inside fenced code blocks
*/
function findUnlinkedDenoApis(
content: string,
): { line: number; api: string }[] {
const lines = content.split("\n");
const results: { line: number; api: string }[] = [];
let inCodeBlock = false;

for (let i = 0; i < lines.length; i++) {
const line = lines[i];

if (/^```/.test(line)) {
inCodeBlock = !inCodeBlock;
continue;
}
if (inCodeBlock) continue;

// Match `Deno.something` or `Deno.something()` NOT preceded by [
const regex = /(?<!\[)`(Deno\.[a-zA-Z]\w+(?:\.\w+)*?)(?:\(\))?`/g;
let match;
while ((match = regex.exec(line)) !== null) {
results.push({ line: i + 1, api: match[1] });
}
}

return results;
}

Deno.test("`Deno.*` API references should be linked to /api/deno/", async () => {
const allUnlinked: { file: string; line: number; api: string }[] = [];

for (const dir of DIRS_TO_CHECK) {
for await (
const entry of walk(dir, {
exts: [".md", ".mdx"],
skip: [/migration_guide\.md$/],
})
) {
const content = await Deno.readTextFile(entry.path);
for (const { line, api } of findUnlinkedDenoApis(content)) {
allUnlinked.push({ file: entry.path, line, api });
}
}
}

if (allUnlinked.length > 0) {
const report = allUnlinked.map(
({ file, line, api }) =>
`${file}:${line} — \`${api}\` → [\`${api}\`](/api/deno/~/${api})`,
);
console.log(
`\nFound ${allUnlinked.length} unlinked Deno API references:\n`,
);
console.log(report.join("\n"));
console.log();
}

assert(
allUnlinked.length === 0,
`${allUnlinked.length} unlinked Deno API references found (see above)`,
);
});
3 changes: 1 addition & 2 deletions runtime/fundamentals/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ deno run --inspect-brk your_script.ts
## Example with Chrome DevTools

Let's try debugging a program using Chrome Devtools. For this, we'll use
[@std/http/file-server](https://jsr.io/@std/http#file-server), a static file
server.
[`@std/http/file-server`](/runtime/reference/std/http/), a static file server.

Use the `--inspect-brk` flag to break execution on the first line:

Expand Down
11 changes: 6 additions & 5 deletions runtime/fundamentals/ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ allows you to:
- Access operating system APIs and hardware features not directly available in
JavaScript

Deno's FFI implementation is based on the `Deno.dlopen` API, which loads dynamic
libraries and creates JavaScript bindings to the functions they export.
Deno's FFI implementation is based on the
[`Deno.dlopen`](/api/deno/~/Deno.dlopen) API, which loads dynamic libraries and
creates JavaScript bindings to the functions they export.

## Security considerations

Expand Down Expand Up @@ -53,7 +54,7 @@ Always ensure you trust the native libraries you're loading through FFI.
The basic pattern for using FFI in Deno involves:

1. Defining the interface for the native functions you want to call
2. Loading the dynamic library using `Deno.dlopen()`
2. Loading the dynamic library using [`Deno.dlopen()`](/api/deno/~/Deno.dlopen)
3. Calling the loaded functions

Here's a simple example loading a C library:
Expand Down Expand Up @@ -300,8 +301,8 @@ Before using FFI, consider these alternatives:

- [WebAssembly](/runtime/reference/wasm/), for portable native code that runs
within Deno's sandbox.
- Use `Deno.command` to execute external binaries and subprocesses with
controlled permissions.
- Use [`Deno.command`](/api/deno/~/Deno.command) to execute external binaries
and subprocesses with controlled permissions.
- Check whether [Deno's native APIs](/api/deno) already provide the
functionality you need.

Expand Down
30 changes: 17 additions & 13 deletions runtime/fundamentals/http_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ HTTP/1.1 and HTTP/2.

### A "Hello World" server

The `Deno.serve` 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).
The [`Deno.serve`](/api/deno/~/Deno.serve) 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).

Here is an example of a server that returns a "Hello, World!" response for each
request:
Expand All @@ -47,13 +47,14 @@ To run this server, you can use the `deno run` command:
deno run --allow-net server.ts
```

There are many more examples of using `Deno.serve` in the
[Examples collection](/examples/#network).
There are many more examples of using [`Deno.serve`](/api/deno/~/Deno.serve) in
the [Examples collection](/examples/#network).

### Listening on a specific port

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:
By default [`Deno.serve`](/api/deno/~/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:

```js title="server.ts"
// To listen on port 4242.
Expand Down Expand Up @@ -159,8 +160,10 @@ 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`).
error in a `write()` call on a [`WritableStream`](/api/web/~/WritableStream)
object that is attached to the response body
[`ReadableStream`](/api/web/~/ReadableStream) object (for example through a
[`TransformStream`](/api/web/~/TransformStream)).

### HTTPS support

Expand Down Expand Up @@ -240,10 +243,11 @@ be compressed automatically:
Deno can upgrade incoming HTTP requests to a WebSocket. This allows you to
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.
To upgrade an incoming [`Request`](/api/web/~/Request) to a WebSocket you use
the [`Deno.upgradeWebSocket`](/api/deno/~/Deno.upgradeWebSocket) function. This
returns an object consisting of a [`Response`](/api/web/~/Response) and a web
standard [`WebSocket`](/api/web/~/WebSocket) object. The returned response
should 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.
Expand Down
4 changes: 2 additions & 2 deletions runtime/fundamentals/linting_and_formatting.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ specify custom settings to tailor the formatting process to your needs.
To use the VSCode ESLint extension in your Deno projects, your project will need
a `node_modules` directory in your project that VSCode extensions can pick up.

In your `deno.json` ensure a `node_modules` folder is created, so the editor can
resolve packages:
In your [`deno.json`](/runtime/fundamentals/configuration/) ensure a
`node_modules` folder is created, so the editor can resolve packages:

```jsonc
{
Expand Down
2 changes: 1 addition & 1 deletion runtime/fundamentals/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Starting with Deno 2.4 it's possible to import `text` and `bytes` modules too.

Support for importing `text` and `bytes` modules is experimental and requires
`--unstable-raw-imports` CLI flag or `unstable.raw-import` option in
`deno.json`.
[`deno.json`](/runtime/fundamentals/configuration/).

:::

Expand Down
69 changes: 38 additions & 31 deletions runtime/fundamentals/open_telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ of the `deno` instrumentation scope. (e.g. `deno:2.1.4`).

Deno automatically creates spans for various operations, such as:

- Incoming HTTP requests served with `Deno.serve`.
- Outgoing HTTP requests made with `fetch`.
- Incoming HTTP requests served with [`Deno.serve`](/api/deno/~/Deno.serve).
- Outgoing HTTP requests made with [`fetch`](/api/web/~/fetch).

#### `Deno.serve`
#### [`Deno.serve`](/api/deno/~/Deno.serve)

When you use `Deno.serve` to create an HTTP server, a span is created for each
incoming request. The span automatically ends when response headers are sent
(not when the response body is done sending).
When you use [`Deno.serve`](/api/deno/~/Deno.serve) to create an HTTP server, a
span is created for each incoming request. The span automatically ends when
response headers are sent (not when the response body is done sending).

The name of the created span is `${method}`. The span kind is `server`.

Expand Down Expand Up @@ -158,10 +158,11 @@ Deno.serve(async (req) => {
});
```

#### `fetch`
#### [`fetch`](/api/web/~/fetch)

When you use `fetch` to make an HTTP request, a span is created for the request.
The span automatically ends when the response headers are received.
When you use [`fetch`](/api/web/~/fetch) to make an HTTP request, a span is
created for the request. The span automatically ends when the response headers
are received.

The name of the created span is `${method}`. The span kind is `client`.

Expand All @@ -181,15 +182,16 @@ After the response is received, the following attributes are added:

The following metrics are automatically collected and exported:

#### `Deno.serve` / `Deno.serveHttp`
#### [`Deno.serve`](/api/deno/~/Deno.serve) / [`Deno.serveHttp`](/api/deno/~/Deno.serveHttp)

##### `http.server.request.duration`

A histogram of the duration of incoming HTTP requests served with `Deno.serve`
or `Deno.serveHttp`. The time that is measured is from when the request is
received to when the response headers are sent. This does not include the time
to send the response body. The unit of this metric is seconds. The histogram
buckets are
A histogram of the duration of incoming HTTP requests served with
[`Deno.serve`](/api/deno/~/Deno.serve) or
[`Deno.serveHttp`](/api/deno/~/Deno.serveHttp). The time that is measured is
from when the request is received to when the response headers are sent. This
does not include the time to send the response body. The unit of this metric is
seconds. The histogram buckets are
`[0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0]`.

This metric is recorded with the following attributes:
Expand All @@ -207,10 +209,12 @@ This metric is recorded with the following attributes:

##### `http.server.active_requests`

A gauge of the number of active requests being handled by `Deno.serve` or
`Deno.serveHttp` at any given time. This is the number of requests that have
been received but not yet responded to (where the response headers have not yet
been sent). This metric is recorded with the following attributes:
A gauge of the number of active requests being handled by
[`Deno.serve`](/api/deno/~/Deno.serve) or
[`Deno.serveHttp`](/api/deno/~/Deno.serveHttp) at any given time. This is the
number of requests that have been received but not yet responded to (where the
response headers have not yet been sent). This metric is recorded with the
following attributes:

- `http.request.method`: The HTTP method of the request.
- `url.scheme`: The scheme of the request URL.
Expand All @@ -220,8 +224,9 @@ been sent). This metric is recorded with the following attributes:
##### `http.server.request.body.size`

A histogram of the size of the request body of incoming HTTP requests served
with `Deno.serve` or `Deno.serveHttp`. The unit of this metric is bytes. The
histogram buckets are
with [`Deno.serve`](/api/deno/~/Deno.serve) or
[`Deno.serveHttp`](/api/deno/~/Deno.serveHttp). The unit of this metric is
bytes. The histogram buckets are
`[0, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]`.

This metric is recorded with the following attributes:
Expand All @@ -240,8 +245,9 @@ This metric is recorded with the following attributes:
##### `http.server.response.body.size`

A histogram of the size of the response body of incoming HTTP requests served
with `Deno.serve` or `Deno.serveHttp`. The unit of this metric is bytes. The
histogram buckets are
with [`Deno.serve`](/api/deno/~/Deno.serve) or
[`Deno.serveHttp`](/api/deno/~/Deno.serveHttp). The unit of this metric is
bytes. The histogram buckets are
`[0, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]`.

This metric is recorded with the following attributes:
Expand Down Expand Up @@ -721,9 +727,9 @@ By default, Deno supports the following propagators:

:::note

These propagators automatically work with Deno's `fetch` API and `Deno.serve`,
enabling end-to-end tracing across HTTP requests without manual context
management.
These propagators automatically work with Deno's [`fetch`](/api/web/~/fetch) API
and [`Deno.serve`](/api/deno/~/Deno.serve), enabling end-to-end tracing across
HTTP requests without manual context management.

:::

Expand Down Expand Up @@ -778,9 +784,10 @@ limitations to be aware of:
- HTTP methods are that are not known are not normalized to `_OTHER` in the
`http.request.method` span attribute as per the OpenTelemetry semantic
conventions.
- The HTTP server span for `Deno.serve` does not have an OpenTelemetry status
set, and if the handler throws (ie `onError` is invoked), the span will not
have an error status set and the error will not be attached to the span via
event.
- The HTTP server span for [`Deno.serve`](/api/deno/~/Deno.serve) does not have
an OpenTelemetry status set, and if the handler throws (ie `onError` is
invoked), the span will not have an error status set and the error will not be
attached to the span via event.
- There is no mechanism to add a `http.route` attribute to the HTTP client span
for `fetch`, or to update the span name to include the route.
for [`fetch`](/api/web/~/fetch), or to update the span name to include the
route.
29 changes: 16 additions & 13 deletions runtime/fundamentals/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,14 @@ resolves to a sensitive system path, additional permissions are required:
- **`/dev/null`, `/dev/zero`, `/dev/random`, `/dev/urandom`**: These safe device
files are always accessible without additional permissions.

Creating symlinks with `Deno.symlink()` requires both `--allow-read` and
`--allow-write` with full access (not path-specific), because symlinks can point
to arbitrary locations.
Creating symlinks with [`Deno.symlink()`](/api/deno/~/Deno.symlink) requires
both `--allow-read` and `--allow-write` with full access (not path-specific),
because symlinks can point to arbitrary locations.

> **Note**: Symlinks that already exist on the filesystem can be read through
> using the permissions for the symlink's location. The full read/write
> permission requirement only applies to _creating_ new symlinks with
> `Deno.symlink()`.
> [`Deno.symlink()`](/api/deno/~/Deno.symlink).

### Network access

Expand Down Expand Up @@ -449,18 +449,21 @@ scripts for npm packages will be executed as a subprocess.
Deno provides an
[FFI mechanism for executing code written in other languages](/runtime/fundamentals/ffi/),
such as Rust, C, or C++, from within a Deno runtime. This is done using the
`Deno.dlopen` API, which can load shared libraries and call functions from them.
[`Deno.dlopen`](/api/deno/~/Deno.dlopen) API, which can load shared libraries
and call functions from them.

By default, executing code can not use the `Deno.dlopen` API, as this would
constitute a violation of the principle that code can not escalate it's
privileges without user consent.
By default, executing code can not use the
[`Deno.dlopen`](/api/deno/~/Deno.dlopen) API, as this would constitute a
violation of the principle that code can not escalate it's privileges without
user consent.

In addition to `Deno.dlopen`, FFI can also be used via Node-API (NAPI) native
addons. These are also not allowed by default.
In addition to [`Deno.dlopen`](/api/deno/~/Deno.dlopen), FFI can also be used
via Node-API (NAPI) native addons. These are also not allowed by default.

Both `Deno.dlopen` and NAPI native addons require explicit permission using the
`--allow-ffi` flag. This flag can be specified with a list of files or
directories to allow access to specific dynamic libraries.
Both [`Deno.dlopen`](/api/deno/~/Deno.dlopen) and NAPI native addons require
explicit permission using the `--allow-ffi` flag. This flag can be specified
with a list of files or directories to allow access to specific dynamic
libraries.

_Like subprocesses, dynamic libraries are not run in a sandbox and therefore do
not have the same security restrictions as the Deno process they are being
Expand Down
Loading
Loading