Files
windmill/backend/windmill-runtime-nativets/src
Ruben Fiszel 3cd0eac8c1 deps: bump deno_core / deno_ast / swc to the goldilocks pin set; drop serde ceiling (#9111)
* deps: bump deno_core / deno_ast / swc to the goldilocks pin set; drop serde ceiling

Bumps every deno_* and swc_* workspace dep to a hand-picked "goldilocks"
combination that drops the serde =1.0.220 ceiling without crashing into
the rustls / aws-sdk resolver wall that the obvious deno v2.6.0 target
hits.

## What's the goldilocks set

| crate            | old      | new       | source                                |
|------------------|----------|-----------|---------------------------------------|
| deno_core        | 0.336.0  | 0.352.0   | deno v2.4.0                           |
| deno_fetch       | 0.214.0  | 0.233.0   | deno v2.4.0                           |
| deno_tls         | 0.177.0  | 0.196.0   | deno v2.4.0 (last permissive-rustls)  |
| deno_console     | 0.190.0  | 0.209.0   | deno v2.4.0                           |
| deno_url         | 0.190.0  | 0.209.0   | deno v2.4.0                           |
| deno_webidl      | 0.190.0  | 0.209.0   | deno v2.4.0                           |
| deno_web         | 0.221.0  | 0.240.0   | deno v2.4.0                           |
| deno_io          | 0.100.0  | 0.119.0   | deno v2.4.0                           |
| deno_net         | 0.182.0  | 0.201.0   | deno v2.4.0                           |
| deno_permissions | 0.49.0   | 0.68.0    | deno v2.4.0                           |
| deno_telemetry   | 0.12.0   | 0.31.0    | deno v2.4.0                           |
| deno_error       | =0.5.5   | =0.6.1    | deno v2.4.0                           |
| deno_ast         | =0.44.0  | =0.51.0   | **override** — see "load-bearing" below |
| deno_fs          | (new)    | 0.119.0   | new workspace dep — FetchPermissions exposes deno_fs::CheckedPath / GetPath as public API |
| v8               | =130.0.7 | =137.1.0  | deno_core 0.352 transitive            |
| swc_common       | =0.37.5  | =14.0.4   | **the load-bearing pin**              |
| swc_ecma_ast     | =0.118.2 | =15.0.0   | matched set with swc_common 14.0.4    |
| swc_ecma_parser  | =0.149.1 | =24.0.3   | matched set                           |
| swc_ecma_visit   | =0.104.8 | =15.0.0   | matched set                           |
| serde            | =1.0.220 | ^1        | **freed** (resolves to 1.0.228+)      |

## Why this combination and not v2.6.0

The obvious target was deno v2.6.0 (with deno_ast 0.52 → swc_common 17,
well past the `__private` ceiling). That hits three resolver collisions:

1. libsqlite3-sys: deno_cache → rusqlite 0.37 → libsqlite3-sys 0.35
   vs sqlx → libsqlite3-sys 0.30. **Already killed by PR #9110** —
   we dropped deno_runtime, which is what pulled in deno_cache.
2. fqdn 0.4.6/0.4.7 yanked, required by deno_permissions 0.81.0. Solvable
   by injecting the yanked entry into Cargo.lock manually but ugly.
3. rustls: deno_tls 0.198+ hard-pins `=0.23.28`, but aws-sdk-bedrockruntime
   1.122.0 → aws-smithy-http-client 1.1.5 wants `^0.23.31`. Within-major
   conflict, no resolver path. The unbeatable wall.

Goldilocks-set choice sidesteps (2) and (3) entirely:

- `deno_tls 0.196.0` was the last version before deno tightened
  `rustls ^0.23.11` (range, accepts 0.23.31) to exact `=0.23.28`. With
  ^0.23.11, the resolver picks rustls 0.23.35 (latest 0.23 patch) which
  satisfies both deno_tls's `>=0.23.11` and aws-sdk's `>=0.23.31`. Verified
  empirically: lockfile has rustls 0.23.35 after this bump.
- `deno_permissions 0.68.0` (v2.4.0's pin) doesn't depend on fqdn at all.
  The fqdn dep was added in a later deno_permissions release.

## Why deno_ast =0.51.0 specifically (not 0.48.0 from v2.4.0)

`swc_common 14.0.4` is the first patch that **drops the
`pub use serde::__private as serde;` line** in `src/private/mod.rs`. Older
14.0.x and all 0.37.5–13.x revisions still have it, and that line is
what was capping `serde = "=1.0.220"` (the workspace pin's "stuck because
of swc" comment). Empirically verified by inspecting the tarballs of
14.0.0 / 14.0.1 / 14.0.2 / 14.0.3 / 14.0.4:

    14.0.0: has hack
    14.0.1: has hack
    14.0.2: has hack
    14.0.3: has hack
    14.0.4: NO HACK    ← inflection point

`deno_ast 0.51.0` pins `swc_common =14.0.4` exactly — older deno_ast
versions pin earlier swc_common patches that still have the hack.
Notably, deno v2.4.0 itself pins `deno_ast =0.48.0` (swc_common 9.2.0,
still has hack) — we deliberately deviate from v2.4.0's deno_ast pin
to escape the swc serde wall, while keeping the rest of v2.4.0's pin
set for resolver compatibility with aws-sdk. deno_ast 0.51 was never
shipped in any deno release (v2.4.5 used 0.49, v2.5.0 jumped to 0.50,
v2.6.0 to 0.52), but it's published on crates.io and compatible with
v2.4.0's deno_core 0.352.

## What this unblocks

- PR #9106's `serde = "=1.0.224"` bump variant can rebase onto this
  and resolve cleanly (MaterializeInc/rust-postgres' `postgres-types`
  needs `serde_core ^1.0.221`, which is satisfied now that we're on
  serde 1.0.228).
- Future deno_* / swc_* bumps no longer need to argue about the serde
  ceiling — it's gone.

## What changes in source code

This commit is Cargo.toml + Cargo.lock only. Source changes that the
new deno_core / deno_fetch API requires live in the follow-up commits:

- `parsers/windmill-parser-{ts,ts-asset,wac}`: swc 0.37 → 14
  (`code.into()` ambiguity fix at 5 sites)
- `windmill-runtime-nativets/build.rs` + `src/lib.rs`: deno_core 0.336
  → 0.352 API moves (`init_ops_and_esm()` → `init()`,
  `FetchPermissions` / `NetPermissions` trait signature updates,
  `deno_tls::Proxy` enum shape change)

A companion change in windmill-ee-private adjusts
`otel_tracing_proxy_ee.rs:521` for `deno_telemetry::init`'s second arg
becoming by-value (was `&OtelConfig`).

* fix(parsers): adapt to swc_common 14 BytesStr ambiguity

swc 0.37.5 → 14.0.4 changed `SourceMap::new_source_file`'s `src` argument
from `String` to `impl Into<BytesStr>`. With `BytesStr` available, the
existing call sites' `code.into()` on a `&str` becomes ambiguous between
`Into<Bytes>` (from the bytes crate) and `Into<BytesStr>` (from
bytes_str). Switch to `code.to_string()` to produce an owned `String`
that satisfies `From<String> for BytesStr` unambiguously.

Five call sites across three crates:
- windmill-parser-ts/src/lib.rs (3 sites)
- windmill-parser-ts-asset/src/lib.rs (1 site)
- windmill-parser-wac/src/typescript.rs (1 site)

* fix(nativets): adapt to deno_core 0.352 / deno_fetch 0.233 API changes

The goldilocks deno bump (deno_core 0.336 → 0.352, deno_fetch 0.214 →
0.233, etc.) ripples through nativets' build.rs and src/lib.rs.
Source-level changes required:

## 1. `extension!` macro: `init_ops_and_esm()` and `init_ops()` removed

deno_core 0.352's `extension!` macro now generates a single `init()`
function on the extension struct (full: ops + esm), plus `lazy_init()`
(ops only, with `needs_lazy_init = true` and a contract that the
caller invokes `JsRuntime::lazy_init_extensions` after construction).

- `build.rs` (snapshot creation, wants both ops and esm baked in):
  `X::init_ops_and_esm(...)` → `X::init(...)`.
- `src/lib.rs:create_nativets_runtime` (runtime, was using `init_ops()`
  because the snapshot already provides esm): also → `X::init(...)`.
  deno_core's snapshot path skips esm re-execution when the snapshot
  provides them, so the esm registration is a no-op at runtime. This
  is how deno's own v2.4.0 runtime works.

Avoided `lazy_init` because it requires plumbing
`JsRuntime::lazy_init_extensions(ext_args_vec)` correctly across the
codebase, which is invasive for no behavioural benefit.

## 2. Local `fetch` extension now declared in both build.rs and lib.rs

deno_core 0.352 validates extension order between snapshot and runtime.
Our snapshot's last extension is the local `fetch` ext (which provides
ext:fetch/src/runtime.js). To avoid a runtime panic:

    "Extensions from snapshot loaded in wrong order: expected fetch but got windmill"

…the runtime extension list now ends with `fetch::init()` matching the
snapshot order. The macro requires the same `esm` argument to type-check,
even though the ESM is not re-executed at runtime (it's in the snapshot).

## 3. `FetchPermissions` and `NetPermissions` trait shape

`deno_fetch::FetchPermissions` (deno_fetch 0.233.0) added new methods
and changed signatures:

- `check_read` / `check_write`: now take `path: Cow<'a, Path>` plus
  a new `get_path: &'a dyn deno_fs::GetPath` parameter, and return
  `Result<deno_fs::CheckedPath<'a>, FsError>` instead of `Result<Cow<Path>, FsError>`.
- New `check_write` (didn't exist) and `check_net_vsock` methods.

`deno_net::NetPermissions` (deno_net 0.201.0) gained `check_vsock`
and `check_write_path` now takes `Cow<'_, Path>`.

For `build.rs`'s `PermissionsContainer` (used only during snapshot
creation, where permissions are never actually checked): all methods
`unreachable!("snapshotting")`.

For `src/lib.rs`'s `PermissionsContainer` (used at runtime — the
nativets policy is "allow everything"): `check_read` / `check_write`
return `Ok(CheckedPath::Unresolved(path))`, `check_*_vsock` return
`Ok(())`. Smoke tests confirm fetch/net/url/web/blob/timers/structuredClone
behaviour is intact end-to-end.

## 4. `deno_tls::Proxy` is now an enum

`deno_tls::Proxy` was a struct, is now an enum with `Http`, `Https`,
`Socks5` variants. Our call site uses HTTP proxies — switched the
struct literal `deno_tls::Proxy { url, basic_auth }` to
`deno_tls::Proxy::Http { url, basic_auth }`.

## 5. New `deno_fs` direct workspace dep

`FetchPermissions` exposes `deno_fs::CheckedPath` and `deno_fs::GetPath`
as part of its public API. We can't avoid naming `deno_fs` directly any
more. Pinned to 0.119.0 (v2.4.0's matched version, transitively present
already through deno_fetch). Added to workspace `[dependencies]` plus
nativets's `[dependencies]` and `[build-dependencies]`.

## Validation

`cargo check --features enterprise,deno_core,duckdb,license,python,rust,scoped_cache,parquet,private,private_registry_test,csharp,php,ruby,mysql,quickjs,mcp,run_inline`
→ clean.

`cargo test -p windmill-runtime-nativets smoke -- --ignored --skip smoke_net_`
→ 8 passed; 0 failed (the full local smoke suite covering fetch,
setTimeout/Promise.all, URL/SearchParams, Blob/btoa/atob, large payload
roundtrip, error propagation, concurrent isolates, TS enum/union
transpile).

Network smoke tests (`smoke_net_fetch_example_com`,
`smoke_net_fetch_json_and_headers`) not run as part of the validation
gate but expected to pass — the change preserves deno_fetch behaviour
through the trait surface.

* chore: update ee-repo-ref to pick up deno_telemetry::init by-value fix

Points at windmill-ee-private branch deps/bump-deno-and-swc-goldilocks
which contains the companion otel_tracing_proxy_ee.rs adjustment for
deno_telemetry 0.12 → 0.31 (second arg of `init` is now by-value).
EE-only file, doesn't affect OSS build.

* chore(nix): bump rusty_v8 in flake.nix to 137.1.0 to match Cargo.toml

Cargo.toml's v8 pin moved from =130.0.7 to =137.1.0 as part of the
deno_core 0.336 → 0.352 bump, but I missed the comment directly above
the version pin:

    # Exact version NOTE: Do not forget to update version and hash in flake.nix

flake.nix provides the prebuilt librusty_v8 binary that the v8 crate
links against. A version mismatch would either fail to fetch (if the
137.1.0 release didn't exist) or cause link-time symbol mismatches.
Nix is used by rust-client-check.yml and rust_on_release.yml in CI,
plus the dev shell — stale flake pin breaks all of those.

Updates x86_64-linux's sha256 to match the actual hash of
librusty_v8_release_x86_64-unknown-linux-gnu.a.gz at the 137.1.0 tag.
Other targets (aarch64-linux, x86_64-darwin, aarch64-darwin) remain
as lib.fakeHash — they were already placeholders in the previous
pin, so we don't regress on them.

Caught by both cubic and Pi reviewers on PR #9111.

* docs(nativets): clarify snapshot-prefix rule in extension-order comment

Claude reviewer caught that the doc comment claimed the runtime
extension list matches the snapshot's order — implying an exact match.
The truth is more permissive: deno_core 0.352 requires the snapshot's
extension list to be a *prefix* of the runtime's, not an exact match.
Runtime is allowed to append extra extensions (which we do — the
windmill `ext` carrying our ops is the last entry at runtime but absent
from the snapshot).

The code is correct as-is; only the comment wording was misleading.

Also fixes the same wording in PR description.
2026-05-11 21:13:24 +00:00
..