Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
974b08d
fix(std): match Node 24 in the node:http agent
vados-cosmonic Sep 4, 2026
6d8396c
fix(std): give agent: false requests a fresh node:http agent
vados-cosmonic Sep 4, 2026
d8eb97a
fix(std): reject non-object node:http server options
vados-cosmonic Sep 4, 2026
d66f497
feat(std): add the node:https shim
vados-cosmonic Sep 4, 2026
0af5c0f
test(std): add node:https unit tests
vados-cosmonic Sep 4, 2026
3c3b457
feat(jco): resolve node:https through the builtin plugin
vados-cosmonic Sep 4, 2026
9f6e7e1
docs(std): document node:https
vados-cosmonic Sep 4, 2026
5cb6216
test(jco): add node:https plugin and guest tests
vados-cosmonic Sep 4, 2026
d2ae092
feat(std): add node:net address utilities and option types
vados-cosmonic Sep 5, 2026
73f95e5
refactor(std): share WASI TCP transport across HTTP implementations
vados-cosmonic Sep 5, 2026
deff4b8
test(std): use the shared transport in HTTP socket tests
vados-cosmonic Sep 5, 2026
d22a53e
feat(std): add WASI-backed node:net sockets
vados-cosmonic Sep 5, 2026
06c9720
feat(std): expose node:net servers and module exports
vados-cosmonic Sep 5, 2026
6df0764
test(std): cover node:net conformance and socket lifecycles
vados-cosmonic Sep 5, 2026
95c5b7e
feat(jco): resolve node:net through the builtin plugin
vados-cosmonic Sep 5, 2026
1de5b5e
test(jco): cover node:net adapters and WIT imports
vados-cosmonic Sep 5, 2026
419ee0a
test(jco): exercise node:net in QuickJS and StarlingMonkey
vados-cosmonic Sep 5, 2026
b4ecab6
docs(std): document node:net support and limitations
vados-cosmonic Sep 5, 2026
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
190 changes: 136 additions & 54 deletions docs/src/interop/nodejs-builtins.md

Large diffs are not rendered by default.

67 changes: 56 additions & 11 deletions packages/jco-std/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Below is a list of utilties provided by `@bytecodealliance/jco-std`:
| `wasi/0.2.x/node/24.x.x/fs` | `node:fs` and `node:fs/promises` over an explicit host capability |
| `wasi/0.2.x/node/24.x.x/http` | `node:http` API with direct, WASI sockets, and WASI HTTP implementations |
| `wasi/0.2.x/node/24.x.x/http2` | `node:http2` API with direct and cleartext WASI sockets implementations |
| `wasi/0.2.x/node/24.x.x/https` | `node:https` API sharing the `node:http` core and implementations |
| `wasi/0.2.x/node/24.x.x/net` | `node:net` module over WASI Preview 2 0.2.12 sockets |
| `wasi/0.2.x/node/24.x.x/net/core` | `node:net` core over injected WASI Preview 2 sockets |
| `wasi/0.2.x/node/24.x.x/os` | `node:os` guest adapter over an explicit host capability |
| `wasi/0.2.x/node/24.x.x/path` | `node:path` adapter, Node 24 on WASI p2 |
| `wasi/0.2.x/node/24.x.x/string-decoder` | Guest-local `node:string_decoder` implementation for Node 24 |
Expand Down Expand Up @@ -63,7 +66,8 @@ Below is a list of utilties provided by `@bytecodealliance/jco-std`:
| `wasi/0.2.x/node/24.x.x/http/impl/wasi-sockets` | `node:http` implementation over WASI Preview 2 sockets |
| `wasi/0.2.x/node/24.x.x/http/impl/wasi-http` | `node:http` implementation over WASI Preview 2 HTTP |
| `wasi/0.2.x/node/24.x.x/http/host` | Deny-by-default host for `jco:node/http` |
| `wasi/0.2.x/node/24.x.x/http/host/node` | Opt-in host over the runtime's real `node:http` |
| `wasi/0.2.x/node/24.x.x/http/host/node` | Opt-in host over the runtime's real `node:http` and `node:https` |
| `wasi/0.2.x/node/24.x.x/https/core` | `node:https` core shared by the selectable implementations |
| `wasi/0.2.x/node/24.x.x/os/host` | Deny-by-default host for `jco:node/os` |
| `wasi/0.2.x/node/24.x.x/os/host/node` | Opt-in host over the runtime's real `node:os` |
| `node/path` | Legacy unversioned alias for `wasi/0.2.x/node/24.x.x/path` |
Expand Down Expand Up @@ -146,8 +150,9 @@ Jco can bundle the following Node.js APIs into JavaScript WebAssembly components
`@bytecodealliance/jco-std/wasi/0.2.x/node/24.x.x/inspector` and the
application-provided `jco:node/inspector@0.1.0` capability, with the host
calling back into the component through a guest-exported callbacks interface;
- the `node:http` API, with selectable direct, `wasi:sockets`, and `wasi:http`
implementations;
- the `node:http` and `node:https` APIs, with selectable direct,
`wasi:sockets`, and `wasi:http` implementations;
- the `node:net` TCP client/server and address APIs over `wasi:sockets`;
- `node:buffer`, with its modern core provided by Jco's audited unenv
compatibility layer;
- `node:querystring`, provided by Jco's audited unenv compatibility layer;
Expand Down Expand Up @@ -543,6 +548,28 @@ interface does not expose an in-flight c-ares request as a resource that a later
guest call could cancel. The WIT boundary remains runtime-neutral so a browser DNS
provider can be added later.

### Net

`node:net` uses Preview 2 DNS, TCP, IO streams, and pollables directly. Jco adds
the matching `wasi:sockets` and `wasi:io` imports for the selected 0.2.12 or
0.2.10 world; it does not add a Jco-specific network capability. Ordinary TCP
client and server code remains unchanged:

```js
import { connect, createServer } from "node:net";

createServer((socket) => socket.end("hello")).listen(8080, "127.0.0.1");
connect(8080, "127.0.0.1").setEncoding("utf8").on("data", console.log);
```

The module also provides `BlockList`, `SocketAddress`, IP predicates,
`BoundSocket`, family-selection defaults, and Node 24.19's exact named-export
surface. Unix-domain sockets, named pipes, arbitrary file-descriptor/libuv
handles, custom DNS callbacks, and socket options missing from Preview 2 are
rejected explicitly. `Socket` provides the common Duplex-shaped API but cannot
inherit from a classic `node:stream.Duplex` until that stream implementation is
available.

### HTTP

Application code uses the ordinary Node API:
Expand Down Expand Up @@ -577,7 +604,19 @@ const server = createServer((request, response) => {
server.listen(8080, "127.0.0.1");
```

Bundle it and select how `node:http` reaches the host:
`node:https` is the same core with the `https:` profile, port 443, and a
TLS-aware `Agent`. Servers take Node's TLS options and clients take the
`tls.connect` subset (`ca`, `cert`, `key`, `rejectUnauthorized`, `servername`,
`ALPNProtocols`, and so on), which cross the boundary as a typed record:

```js
import { createServer, get } from "node:https";

createServer({ key, cert }, (request, response) => response.end("secure")).listen(8443);
get("https://localhost:8443/", { ca: cert }, (response) => response.resume());
```

Bundle it and select how `node:http` and `node:https` reach the host:

```console
jco componentize component.js --wit wit --bundle \
Expand All @@ -589,12 +628,17 @@ jco componentize component.js --wit wit --bundle \
- `direct` (the default), which adds `jco:node/http@0.1.0`; its default provider
throws `ERR_JCO_HTTP_ADAPTER_REQUIRED`, and a Node application can explicitly
map `wasi/0.2.x/node/24.x.x/http/host/node` when transpiling. It supports
clients and servers through real `node:http`;
clients and servers through real `node:http`, and terminates TLS for
`node:https` through real `node:https`;
- `wasi-sockets`, which implements HTTP/1.1 in the guest using only Preview 2
socket and IO capabilities, including TCP servers; and
socket and IO capabilities, including TCP servers. It has no TLS stack, so
`node:https` clients and servers are refused rather than served in
plaintext; and
- `wasi-http`, which translates requests to Preview 2
`wasi:http/outgoing-handler`. It rejects `Server` construction immediately
because an outgoing-handler cannot listen for arbitrary inbound connections.
`wasi:http/outgoing-handler`, including `https` URLs, though per-request TLS
options are refused because the outgoing-handler owns certificate
validation. It rejects `Server` construction immediately because an
outgoing-handler cannot listen for arbitrary inbound connections.

When the selected world is missing a required import or callback export, Jco
edits that world in place, adds generated comments and declarations, installs
Expand All @@ -608,9 +652,10 @@ WIT package defines multiple worlds.

The initial implementation buffers each request and response at the
implementation boundary. Client and server objects retain Node-style callbacks
and events inside the guest. Connection pooling, upgrades, CONNECT tunnels,
HTTPS, and persistent HTTP/1.1 connections in the `wasi-sockets` implementation
are not implemented; unavailable operations throw explicit errors.
and events inside the guest. Connection pooling, upgrades, CONNECT proxy
tunnels, and persistent HTTP/1.1 connections in the `wasi-sockets`
implementation are not implemented; unavailable operations throw explicit
errors.

### HTTP/2

Expand Down
20 changes: 20 additions & 0 deletions packages/jco-std/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,26 @@
"types": "./dist/wasi/0.2.x/node/24.x.x/http2-host-node.d.ts",
"node": "./dist/wasi/0.2.x/node/24.x.x/http2-host-node.js"
},
"./wasi/0.2.x/node/24.x.x/https": {
"types": "./dist/wasi/0.2.x/node/24.x.x/https.d.ts",
"browser": "./dist/wasi/0.2.x/node/24.x.x/https.js",
"default": "./dist/wasi/0.2.x/node/24.x.x/https.js"
},
"./wasi/0.2.x/node/24.x.x/https/core": {
"types": "./dist/wasi/0.2.x/node/24.x.x/https/core.d.ts",
"browser": "./dist/wasi/0.2.x/node/24.x.x/https/core.js",
"default": "./dist/wasi/0.2.x/node/24.x.x/https/core.js"
},
"./wasi/0.2.x/node/24.x.x/net": {
"types": "./dist/wasi/0.2.x/node/24.x.x/net.d.ts",
"browser": "./dist/wasi/0.2.x/node/24.x.x/net.js",
"default": "./dist/wasi/0.2.x/node/24.x.x/net.js"
},
"./wasi/0.2.x/node/24.x.x/net/core": {
"types": "./dist/wasi/0.2.x/node/24.x.x/net/core.d.ts",
"browser": "./dist/wasi/0.2.x/node/24.x.x/net/core.js",
"default": "./dist/wasi/0.2.x/node/24.x.x/net/core.js"
},
"./wasi/0.2.x/node/24.x.x/path": {
"types": "./dist/wasi/0.2.x/node/24.x.x/path.d.ts",
"browser": "./dist/wasi/0.2.x/node/24.x.x/path.js",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
declare module 'wasi:cli/environment@0.2.12' {
/**
* Get the POSIX-style environment variables.
*
*
* Each environment variable is provided as a pair of string variable names
* and string value.
*
*
* Morally, these are a value import, but until value imports are available
* in the component model, this import function should return the same
* values each time it is called.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
declare module 'wasi:clocks/monotonic-clock@0.2.12' {
/**
* Read the current value of the clock.
*
*
* The clock is monotonic, therefore calling this function repeatedly will
* produce a sequence of non-decreasing values.
*
*
* For completeness, this function traps if it's not possible to represent
* the value of the clock in an `instant`. Consequently, implementations
* should ensure that the starting time is low enough to avoid the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
declare module 'wasi:config/store@0.2.0-rc.1' {
/**
* Gets a configuration value of type `string` associated with the `key`.
*
*
* The value is returned as an `option<string>`. If the key is not found,
* `Ok(none)` is returned. If an error occurs, an `Err(error)` is returned.
*/
export function get(key: string): string | undefined;
/**
* Gets a list of configuration key-value pairs of type `string`.
*
*
* If an error occurs, an `Err(error)` is returned.
*/
export function getAll(): Array<[string, string]>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ declare module 'wasi:http/incoming-handler@0.2.12' {
* method, which allows execution to continue after the response has been
* sent. This enables both streaming to the response body, and performing other
* work.
*
*
* The implementor of this function must write a response to the
* `response-outparam` before returning, or else the caller will respond
* with an error on its behalf.
Expand Down
Loading
Loading