Skip to content

refactor(tsc): defer web-platform globals to lib.dom in deno libs#35639

Merged
bartlomieju merged 2 commits into
mainfrom
feat/lib-deno-defer
Jul 8, 2026
Merged

refactor(tsc): defer web-platform globals to lib.dom in deno libs#35639
bartlomieju merged 2 commits into
mainfrom
feat/lib-deno-defer

Conversation

@bartlomieju

@bartlomieju bartlomieju commented Jun 30, 2026

Copy link
Copy Markdown
Member

Reshapes the web-platform declare var declarations in Deno's bundled
lib.deno_*.d.ts so each global re-exports lib.dom's type when lib.dom is
present and otherwise keeps Deno's own type, using the same conditional-deferral
pattern @types/node already uses to coexist with lib.dom:

declare var Request:
  typeof globalThis extends { document: any; Request: infer T } ? T
    : { readonly prototype: Request; new (/* ... */): Request };

document is a DOM-exclusive marker (Deno's own globals never declare it), so on
a normal Deno program the conditional always resolves to Deno's own type. This is
behaviour-neutral today: the full check spec suite passes unchanged. It only
takes effect when lib.dom is also loaded, where each global now defers to the
DOM definition instead of colliding with it.

The motivation is to let Deno's libs coexist with a single global symbol table
(stock TypeScript and @types/node) rather than relying on the bundled
compiler's dual node/deno global tables. This is the first, behaviour-neutral
step of that work; nothing about the default Deno experience changes.

The change is generated and reproducible via tools/apply_web_globals_deferral.ts,
which derives the overlapping name set from TYPES_NODE_IGNORABLE_NAMES and
rewrites the affected type nodes in place so comments and formatting are
preserved.


Part of the broader effort to drop Deno's forked TypeScript; see #35621 for context and the overall plan.

Wrap each web-platform `declare var` in cli/tsc/dts/lib.deno_*.d.ts that
overlaps with @types/node in a
`typeof globalThis extends { document: any; Name: infer T } ? T : <original>`
conditional, so each global re-exports lib.dom's type when lib.dom is loaded
(precedence dom > deno) and lets stock @types/node's own
`typeof globalThis extends { onmessage: any; Name: infer T }` probe defer to
Deno's declaration otherwise (precedence deno > node).

Behaviour-neutral under the current forked tsc: a Deno file's globalThis has no
`document`, so the conditional always yields the original Deno type. This is
groundwork for removing the fork's dual node/deno global symbol-table split.

Generated by tools/apply_web_globals_deferral.ts (derives the overlap set from
TYPES_NODE_IGNORABLE_NAMES).
@bartlomieju
bartlomieju merged commit 8959589 into main Jul 8, 2026
136 checks passed
@bartlomieju
bartlomieju deleted the feat/lib-deno-defer branch July 8, 2026 15:05
bartlomieju added a commit that referenced this pull request Jul 8, 2026
This drops Deno's forked TypeScript compiler and runs on stock
`[email protected]` from npm (the exact version the fork was based on).
The forked `cli/tsc/00_typescript.js` and its ~466-line patch set are
removed, along with the five `ts.deno.*` host hooks the fork exposed
(`setIsNodeSourceFileCallback`, `setNodeOnlyGlobalNames`,
`setTypesNodeIgnorableNames`, and the LSP span callbacks). Forking tsc
has meant a manual re-port of the patch set and a hand-rebuilt 9 MB bundle
on every upgrade; on stock TypeScript an upgrade becomes a version bump.

The fork's load-bearing patch was a dual node/deno global symbol table
in the checker. That is replaced by a pure `.d.ts` mechanism: Deno's libs
declare the marker globals (`onmessage`/`onabort`/`ReportingObserver`) that stock
`@types/node` probes for, so `@types/node` defers its web-platform
globals to Deno's exactly as it defers to `lib.dom`, and everything resolves
against a single global table. This builds on the prep PRs already merged: the
deferral transform (#35639), the `PerformanceObserver` types (#35640), and single
`@types/node` loading (#35641). It also carries the `URLPattern`
concession (`@types/node` declares it unconditionally, so Deno keeps only the
interface) and tightens `import.meta.dirname`/`filename` to required `string` to
match `@types/node`.

This is a breaking change and targets Deno 3. Five `check` specs are
temporarily disabled with `ignore: true` and a comment pointing at their
follow-ups: `check_workspace` and the marker interaction, the `export =`
declaration-file case, per-member `jsxImportSource`
(`jsx_import_source_different_per_member`), and transitive `@types/node`
(`express_with_koa`, re-enabled by #35871). The LSP runs on the same
stock compiler; its dedicated verification is still pending.

See #35621 for the full investigation and plan.

Fixes #33012
magurotuna added a commit to denoland/deno_graph that referenced this pull request Jul 9, 2026
Refreshes the ecosystem snapshots that are currently red on CI (surfaced on #658, 2026-07-09).
Regenerated with `UPDATE=1 cargo test --test ecosystem <spec>` against canary
`4064da2bee25c414481dc7985e474b62da497066`, and verified green without `UPDATE` afterwards.

Specs refreshed:

- `bureaudouble/[email protected]`
- `ipinfo/[email protected]` … `1.0.7`
- `mebus/[email protected]`, `@1.0.2`

All are **canary drift**, not registry drift (an earlier attribution in #659 was wrong — see the
correction comment there):

- **`bureaudouble/[email protected]`** — bisected to denoland/deno#35639 ("defer web-platform globals to
  lib.dom in deno libs"): the error set (TS2304/TS2552) is unchanged, but the TS2552
  related-information snippet quotes `CloseEvent`'s declaration, whose text changed with the lib
  restructuring (`declare var CloseEvent: { ... }` → `typeof globalThis extends ...` form).
- **`ipinfo/client` and `mebus/mebus`** — `TYPE CHECK FAILED` → `PASSED` from the Deno 2.8 → 2.9
  transition (npm types resolution improved: `mebus` no longer errors on `[email protected]`'s default
  import, TS1192; `ipinfo` no longer errors on the `puppeteer` namespace, TS2503). The minimal repro
  fails on Deno 2.8.3 (matching the old snapshots) and passes on 2.9.1+. The main ecosystem workflow
  has in fact been red for these since 2026-06-22 (last green: 2026-06-10) — it went unnoticed
  because it isn't a required check.

Note: beyond the snapshot refresh, the process problem is that the ecosystem workflow stayed red on
main for weeks without anyone noticing — #659's correction comment discusses that; this PR just
brings the snapshots in line with what CI observes today.

Closes #659
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant