Merge perf/shape-overlay-cost

This commit is contained in:
Chris Tate
2026-10-26 11:53:34 -05:00
1145 changed files with 73292 additions and 17811 deletions
+35
View File
@@ -130,6 +130,8 @@ jobs:
SCRIPTC_TEST_WORKERS: "1"
- name: Verify mixed-source generated AST getters
run: pnpm generate:ts7-ast --check
- name: Verify the generated IR field readers
run: pnpm generate:ir-fields --check
native_macos:
needs: [validation_scope, lanes]
@@ -354,6 +356,37 @@ jobs:
- run: tar -xzf "$RUNNER_TEMP/native-linux-x64-gnu.tar.gz"
- run: pnpm test tests/harness/effect.test.ts tests/harness/effect4.test.ts
# The sanitized three.js nodes build alone: beside the san corpus's other
# workers it took 860 to more than 1200 seconds of its shard
# (SCRIPTC_THREE_SANITIZED_NODES_JOB in scripts/ci-test-plan.mjs). It keeps
# the corpus's LeakSanitizer settings.
three_nodes_san:
needs: [validation_scope, lanes, native_linux]
if: ${{ needs.validation_scope.outputs.full == 'true' && needs.lanes.outputs.linux == 'true' }}
name: test (Linux, san, three.js nodes)
runs-on: ubuntu-24.04
timeout-minutes: 40
env:
SCRIPTC_SAN: "1"
ASAN_OPTIONS: detect_leaks=1
LSAN_OPTIONS: suppressions=${{ github.workspace }}/tests/harness/lsan.supp:print_suppressions=0
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11.1.3
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/download-artifact@v4
with:
name: native-linux-x64-gnu
path: ${{ runner.temp }}
- run: tar -xzf "$RUNNER_TEMP/native-linux-x64-gnu.tar.gz"
- run: pnpm test tests/harness/three.test.ts -t "'nodes' runs statically through LLVM on 'native'"
# Shape inference's overlay (opt-in, SCRIPTC_SHAPE_OVERLAY=1) over the
# suites of real packages: nightly and on manual runs only (scope
# shape_overlay runs it alone), outside the `test` roll-up. Every case
@@ -1033,6 +1066,7 @@ jobs:
tests_macos,
native_linux,
effects,
three_nodes_san,
bootstrap_seed,
bootstrap,
linux_host_clang,
@@ -1065,6 +1099,7 @@ jobs:
lane tests_macos "${{ needs.tests_macos.result }}" "${{ needs.lanes.outputs.macos }}"
lane native_linux "${{ needs.native_linux.result }}" "${{ needs.lanes.outputs.linux }}"
lane effects "${{ needs.effects.result }}" "${{ needs.lanes.outputs.effects }}"
lane three_nodes_san "${{ needs.three_nodes_san.result }}" "${{ needs.lanes.outputs.linux }}"
lane bootstrap_seed "${{ needs.bootstrap_seed.result }}" "${{ needs.lanes.outputs.bootstrap }}"
lane bootstrap "${{ needs.bootstrap.result }}" "${{ needs.lanes.outputs.bootstrap }}"
lane linux_host_clang "${{ needs.linux_host_clang.result }}" "${{ needs.lanes.outputs.linux }}"
+93
View File
@@ -0,0 +1,93 @@
name: LLVM distribution
# Builds the LLVM that the Linux release helpers link
# (native/llvm-codegen/llvm-dist.mjs): LLVM from its release sources with
# ThinLTO and native/llvm-codegen/llvm.profdata.gz, for each Linux
# architecture. Each job builds a helper against it and one against LLVM's
# release archive, requires the two to give identical objects on this
# checkout's helper inputs (scripts/check-llvm-dist.mjs), prints both
# helpers' times, and attaches the archive to the LLVM_DIST_TAG release.
# The arm64 build uses the profile collected on x64; its job log reports how
# many functions the profile no longer matches. Run it after a profile refresh
# or an LLVM version change, with a new LLVM_DIST_TAG.
on:
workflow_dispatch:
permissions:
contents: read
concurrency: ${{ github.workflow }}
jobs:
build:
name: Build LLVM (${{ matrix.arch }})
if: github.repository == 'vercel-labs/scriptc'
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-24.04
llvm_asset: LLVM-22.1.8-Linux-X64
- arch: arm64
runner: ubuntu-24.04-arm
llvm_asset: LLVM-22.1.8-Linux-ARM64
runs-on: ${{ matrix.runner }}
# About an hour for LLVM on 4 cores, and 5 minutes for each helper link.
timeout-minutes: 240
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11.1.3
- uses: actions/setup-node@v4
with:
node-version: "24"
cache: pnpm
- name: Install LLVM's release archive and sources
run: |
sudo apt-get update
sudo apt-get install --yes ninja-build zlib1g-dev libzstd-dev
base=https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8
curl -fL --retry 3 -o "$RUNNER_TEMP/llvm.tar.xz" "$base/${{ matrix.llvm_asset }}.tar.xz"
tar -xJf "$RUNNER_TEMP/llvm.tar.xz" -C "$RUNNER_TEMP"
mv "$RUNNER_TEMP/${{ matrix.llvm_asset }}" "$RUNNER_TEMP/llvm-22.1.8"
curl -fL --retry 3 -o "$RUNNER_TEMP/llvm-src.tar.xz" "$base/llvm-project-22.1.8.src.tar.xz"
tar -xJf "$RUNNER_TEMP/llvm-src.tar.xz" -C "$RUNNER_TEMP"
rm "$RUNNER_TEMP/llvm.tar.xz" "$RUNNER_TEMP/llvm-src.tar.xz"
echo "$RUNNER_TEMP/llvm-22.1.8/bin" >> "$GITHUB_PATH"
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @scriptc/compiler --filter scriptc build
- name: Build the distribution
run: >-
node scripts/build-llvm-dist.mjs --source "$RUNNER_TEMP/llvm-project-22.1.8.src"
--prefix "$RUNNER_TEMP/dist/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}"
--archive "$RUNNER_TEMP/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}.tar.xz"
--work "$RUNNER_TEMP/llvm-dist-work"
- name: Build a helper against each LLVM
env:
HELPER: llvm-linux-${{ matrix.arch }}-gnu
run: |
LLVM_DIR="$RUNNER_TEMP/llvm-22.1.8/lib/cmake/llvm" pnpm --filter "@scriptc/$HELPER" build:native
cp "packages/$HELPER/bin/scriptc-llvm-codegen" "$RUNNER_TEMP/helper-release-archive"
LLVM_DIR="$RUNNER_TEMP/dist/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}/lib/cmake/llvm" \
SCRIPTC_LLVM_THINLTO=1 pnpm --filter "@scriptc/$HELPER" build:native
cp "packages/$HELPER/bin/scriptc-llvm-codegen" "$RUNNER_TEMP/helper-profiled"
- name: Compare the helpers
run: >-
node scripts/check-llvm-dist.mjs --baseline "$RUNNER_TEMP/helper-release-archive"
--candidate "$RUNNER_TEMP/helper-profiled" --rounds 3 --work "$RUNNER_TEMP/llvm-check"
- name: Attach the archive to the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ARCHIVE: ${{ runner.temp }}/scriptc-llvm-22.1.8-linux-${{ matrix.arch }}.tar.xz
run: |
tag=$(node --input-type=module -e "import { LLVM_DIST_TAG } from './native/llvm-codegen/llvm-dist.mjs'; console.log(LLVM_DIST_TAG)")
# Both architectures' jobs create the release if it is missing.
gh release view "$tag" > /dev/null 2>&1 ||
gh release create "$tag" --target "$GITHUB_SHA" --title "$tag" --latest=false \
--notes "LLVM 22.1.8 built with ThinLTO and the helper profile, for the Linux LLVM helpers (scripts/build-llvm-dist.mjs)." ||
gh release view "$tag" > /dev/null
gh release upload "$tag" "$ARCHIVE" "$ARCHIVE.sha256" --clobber
+117 -17
View File
@@ -83,6 +83,7 @@ jobs:
spawnSync('git', ['diff', '--quiet', run.head_sha, 'HEAD', '--', '.',
':(exclude).github/workflows/release.yml', ':(exclude)scripts/verify-native-cli.mjs',
':(exclude)scripts/package-native-cli.mjs', ':(exclude)tests/harness/native-cli-packaging.test.ts',
':(exclude)scripts/wait-npm-available.mjs', ':(exclude)tests/harness/npm-available.test.ts',
]).status !== 0) continue;
const artifacts = api(`repos/${repo}/actions/runs/${run.id}/artifacts?per_page=100`).artifacts
.filter((artifact) => !artifact.expired && artifact.size_in_bytes > 0);
@@ -100,11 +101,11 @@ jobs:
if (receiptRun) appendFileSync(process.env.GITHUB_OUTPUT, `receipt_run=${receiptRun}\n`);
NODE
# Collects the native compiler's profile on this commit
# (scripts/refresh-cli-profile.mjs), so every platform's CLI build optimizes
# with a profile of the code it compiles. The committed profile falls behind
# main within a day or two. If this job fails, the CLI builds use the
# committed profile.
# Collects the native compiler's profile and function layout on this commit
# (scripts/refresh-cli-profile.mjs, scripts/refresh-cli-layout.mjs), so every
# platform's CLI build optimizes and lays out the code it compiles. The
# committed ones fall behind main within a day or two. If this job fails,
# the CLI builds use the committed profile and layout.
cli-profile:
name: Collect the native compiler profile
needs: check-release
@@ -138,11 +139,17 @@ jobs:
- name: Collect the profile
run: >-
node scripts/refresh-cli-profile.mjs --tsc-ts "$RUNNER_TEMP/tsc-ts" --jobs 4
--output "$RUNNER_TEMP/cli-profile/cli.profdata.gz"
--output "$RUNNER_TEMP/cli-profile/cli.profdata.gz" --work "$RUNNER_TEMP/cli-profile-work"
- name: Collect the function layout
run: >-
node scripts/refresh-cli-layout.mjs --jobs 4 --instrumented "$RUNNER_TEMP/cli-profile-work/cli"
--output "$RUNNER_TEMP/cli-profile/cli.layout.gz"
- uses: actions/upload-artifact@v4
with:
name: cli-profile
path: ${{ runner.temp }}/cli-profile/cli.profdata.gz
path: |
${{ runner.temp }}/cli-profile/cli.profdata.gz
${{ runner.temp }}/cli-profile/cli.layout.gz
retention-days: 7
if-no-files-found: error
@@ -173,6 +180,7 @@ jobs:
runtime: runtime-linux-x64-gnu
cli: cli-linux-x64-gnu
llvm_asset: LLVM-22.1.8-Linux-X64
llvm_dist: x64
use_zig: true
- platform: linux-arm64
runner: ubuntu-24.04-arm
@@ -180,6 +188,7 @@ jobs:
runtime: runtime-linux-arm64-gnu
cli: cli-linux-arm64-gnu
llvm_asset: LLVM-22.1.8-Linux-ARM64
llvm_dist: arm64
use_zig: true
- platform: windows-x64
runner: windows-2022
@@ -195,6 +204,7 @@ jobs:
seed_helper: llvm-linux-x64-gnu
cli_target: x86_64-linux-musl
llvm_asset: LLVM-22.1.8-Linux-X64
llvm_dist: x64
use_zig: true
- platform: linux-arm64-musl
runner: ubuntu-24.04-arm
@@ -204,12 +214,14 @@ jobs:
seed_helper: llvm-linux-arm64-gnu
cli_target: aarch64-linux-musl
llvm_asset: LLVM-22.1.8-Linux-ARM64
llvm_dist: arm64
use_zig: true
- platform: wasm32-wasi
runner: ubuntu-24.04
helper: llvm-linux-x64-gnu
runtime: runtime-wasm32-wasi
llvm_asset: LLVM-22.1.8-Linux-X64
llvm_dist: x64
use_zig: true
runs-on: ${{ matrix.runner }}
# The Intel macOS build took 24 minutes for 0.3.2 and passed 30 for 0.3.3.
@@ -240,6 +252,28 @@ jobs:
mv "$RUNNER_TEMP/${{ matrix.llvm_asset }}" "$RUNNER_TEMP/llvm-22.1.8"
echo "LLVM_DIR=$RUNNER_TEMP/llvm-22.1.8/lib/cmake/llvm" >> "$GITHUB_ENV"
echo "$RUNNER_TEMP/llvm-22.1.8/bin" >> "$GITHUB_PATH"
# The Linux helpers link LLVM built with ThinLTO and a profile of the
# helper's code generation (native/llvm-codegen/llvm-dist.mjs), from a
# release of this repository. Without that archive they link LLVM's
# release archive, which gives the same objects more slowly. The
# wasm32-wasi job also uploads the x64 GNU helper, so it selects the same.
- name: Select the profiled LLVM distribution (Linux)
if: matrix.llvm_dist != ''
env:
ARCH: ${{ matrix.llvm_dist }}
run: |
tag=$(node --input-type=module -e "import { LLVM_DIST_TAG } from './native/llvm-codegen/llvm-dist.mjs'; console.log(LLVM_DIST_TAG)")
asset=$(node --input-type=module -e "import { llvmDistAsset } from './native/llvm-codegen/llvm-dist.mjs'; console.log(llvmDistAsset(process.env.ARCH))")
base="https://github.com/$GITHUB_REPOSITORY/releases/download/$tag"
if curl -fsSL --retry 3 -o "$RUNNER_TEMP/$asset" "$base/$asset" &&
curl -fsSL --retry 3 -o "$RUNNER_TEMP/$asset.sha256" "$base/$asset.sha256" &&
(cd "$RUNNER_TEMP" && sha256sum --check "$asset.sha256"); then
tar -xJf "$RUNNER_TEMP/$asset" -C "$RUNNER_TEMP"
echo "SCRIPTC_HELPER_LLVM_DIR=$RUNNER_TEMP/${asset%.tar.xz}/lib/cmake/llvm" >> "$GITHUB_ENV"
echo "The helper links $asset from release $tag"
else
echo "::warning::$asset is not available from release $tag; the helper links LLVM's release archive"
fi
- uses: vercel-labs/setup-zig@v1
if: matrix.use_zig == true
with:
@@ -278,7 +312,15 @@ jobs:
- name: Build native packages (POSIX)
if: matrix.platform != 'windows-x64'
run: |
pnpm --filter @scriptc/${{ matrix.helper }} build:native
if [ -n "${SCRIPTC_HELPER_LLVM_DIR:-}" ]; then
LLVM_DIR="$SCRIPTC_HELPER_LLVM_DIR" SCRIPTC_LLVM_THINLTO=1 pnpm --filter @scriptc/${{ matrix.helper }} build:native || {
echo "::warning::the helper did not build against the profiled LLVM; it links LLVM's release archive"
rm -rf node_modules/.cache/scriptc-${{ matrix.helper }}
pnpm --filter @scriptc/${{ matrix.helper }} build:native
}
else
pnpm --filter @scriptc/${{ matrix.helper }} build:native
fi
if [ "${{ matrix.use_zig }}" = true ]; then
CC=zig AR=zig pnpm --filter @scriptc/${{ matrix.runtime }} build:native
else
@@ -300,8 +342,8 @@ jobs:
with:
name: cli-profile
path: ${{ runner.temp }}/cli-profile
# Without the artifact, SCRIPTC_NATIVE_PROFILE_USE stays unset and
# build-native-cli.mts uses the committed profile.
# Without the artifact, SCRIPTC_NATIVE_PROFILE_USE and SCRIPTC_NATIVE_LAYOUT
# stay unset and build-native-cli.mts uses the committed profile and layout.
- name: Select the native compiler profile
if: matrix.cli != ''
shell: bash
@@ -311,6 +353,11 @@ jobs:
if [ -n "$COLLECTED" ]; then
echo "SCRIPTC_NATIVE_PROFILE_USE=$COLLECTED" >> "$GITHUB_ENV"
echo "The native CLI builds with the profile collected on $GITHUB_SHA"
layout="$(dirname "$COLLECTED")/cli.layout.gz"
if [ -f "$layout" ]; then
echo "SCRIPTC_NATIVE_LAYOUT=$layout" >> "$GITHUB_ENV"
echo "The native CLI builds with the function layout collected on $GITHUB_SHA"
fi
else
echo "::warning::No profile was collected on this commit; the native CLI builds with the committed profile"
fi
@@ -394,6 +441,8 @@ jobs:
contents: read
actions: read
id-token: write
outputs:
uploads: ${{ steps.publish.outputs.uploads }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -413,7 +462,7 @@ jobs:
VERSION: ${{ needs.check-release.outputs.version }}
RECEIPT_RUN: ${{ needs.check-release.outputs.receipt_run }}
run: |
touch "$RUNNER_TEMP/npm-accepted.txt"
touch "$RUNNER_TEMP/npm-accepted.txt" "$RUNNER_TEMP/npm-accepted-times.txt"
# Include this run so re-running only failed jobs restores its receipts.
for run in "$GITHUB_RUN_ID" "$RECEIPT_RUN"; do
if [ -z "$run" ]; then continue; fi
@@ -422,6 +471,7 @@ jobs:
if [ "$count" -eq 0 ]; then continue; fi
gh run download "$run" --repo "$GITHUB_REPOSITORY" --pattern "npm-accepted-$VERSION-*" --dir "$RUNNER_TEMP/npm-receipts/$run"
find "$RUNNER_TEMP/npm-receipts/$run" -name npm-accepted.txt -exec cat {} + >> "$RUNNER_TEMP/npm-accepted.txt"
find "$RUNNER_TEMP/npm-receipts/$run" -name npm-accepted-times.txt -exec cat {} + >> "$RUNNER_TEMP/npm-accepted-times.txt"
done
- name: Setup pnpm
@@ -471,6 +521,7 @@ jobs:
done
- name: Publish to npm
id: publish
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -490,10 +541,14 @@ jobs:
# Upload acceptance and public availability are separate states.
# Save acceptance immediately so retries never depend on registry lag.
# npm-release.txt lists every package of the release, and
# npm-accepted-times.txt the time npm accepted each upload, for the
# npm-available job.
publish_dir() {
dir="$1"
packed="${2:-}"
name=$(node -p "require('./$dir/package.json').name")
echo "$name@$VERSION" >> "$RUNNER_TEMP/npm-release.txt"
if grep -Fxq "$name@$VERSION" "$RUNNER_TEMP/npm-accepted.txt"; then
echo "$name@$VERSION upload already accepted, skipping"
return 0
@@ -510,6 +565,7 @@ jobs:
publish_log="$RUNNER_TEMP/npm-publish.log"
if npm publish "$packed" $PROVENANCE --access public 2>&1 | tee "$publish_log"; then
echo "$name@$VERSION" >> "$RUNNER_TEMP/npm-accepted.txt"
echo "$name@$VERSION $(date +%s)" >> "$RUNNER_TEMP/npm-accepted-times.txt"
return 0
else
publish_status=${PIPESTATUS[0]}
@@ -533,7 +589,8 @@ jobs:
# pnpm pack resolves workspace dependencies; npm handles OIDC.
# Publish dependencies first. Registry propagation after an accepted
# upload must not block the remaining packages or the GitHub release.
# upload must not block the remaining packages; the npm-available
# job waits for it.
publish_dir packages/runtime
publish_dir packages/runtime-darwin-arm64
publish_dir packages/llvm-darwin-arm64
@@ -561,23 +618,66 @@ jobs:
publish_dir packages/cli
echo "All package uploads accepted; npm registry propagation may continue after this job." >> "$GITHUB_STEP_SUMMARY"
# Each package of the release with the time its upload was accepted,
# when a run recorded it.
{
echo "uploads<<NPM_UPLOADS"
awk 'FILENAME == ARGV[1] { accepted[$1] = $2; next } { print $1, accepted[$1] }' \
"$RUNNER_TEMP/npm-accepted-times.txt" "$RUNNER_TEMP/npm-release.txt"
echo "NPM_UPLOADS"
} >> "$GITHUB_OUTPUT"
- name: Save accepted upload receipts
if: always()
uses: actions/upload-artifact@v4
with:
name: npm-accepted-${{ needs.check-release.outputs.version }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/npm-accepted.txt
path: |
${{ runner.temp }}/npm-accepted.txt
${{ runner.temp }}/npm-accepted-times.txt
if-no-files-found: ignore
retention-days: 90
# Publish standalone native distributions and the surface manifest after
# npm publishing succeeds. The release body comes from the marked changelog.
github-release:
name: Create GitHub Release
# Waits until every package of the release resolves on the npm registry,
# and reports each package's time from upload to available. Fails with the
# packages that are still missing after 2 hours. It only reads from the
# registry; the next release run retries it, and publishing skips uploads
# npm already accepted.
npm-available:
name: Wait for npm availability
needs: [check-release, publish]
if: >-
!cancelled() && needs.check-release.outputs.should_release == 'true' && needs.publish.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 135
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Wait for every package to resolve
env:
UPLOADS: ${{ needs.publish.outputs.uploads }}
run: |
printf '%s\n' "$UPLOADS" > "$RUNNER_TEMP/npm-uploads.txt"
node scripts/wait-npm-available.mjs "$RUNNER_TEMP/npm-uploads.txt"
# Publish standalone native distributions and the surface manifest after
# every npm package resolves. The release body comes from the marked
# changelog.
github-release:
name: Create GitHub Release
needs: [check-release, publish, npm-available]
if: >-
!cancelled() && needs.check-release.outputs.should_release == 'true' && needs.npm-available.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
+13 -1
View File
@@ -283,10 +283,22 @@
},
{
// Ambient declarations describe an existing constructor and its prototype methods.
"files": ["packages/compiler/ambient/scriptc-node-fallback.d.ts"],
"files": [
"packages/compiler/ambient/scriptc-node-fallback.d.ts",
"packages/compiler/ambient/node-fallback/*.d.ts",
],
"rules": {
"typescript/no-unsafe-declaration-merging": "off",
},
},
{
// Each module's fallback declarations are a script that declares the
// module ambiently; it names the files of the modules it uses by
// reference, since a script cannot import them.
"files": ["packages/compiler/ambient/node-fallback/*.d.ts"],
"rules": {
"typescript/triple-slash-reference": "off",
},
},
],
}
+2
View File
@@ -46,6 +46,8 @@ SCRIPTC_TEST_WORKERS=4 SCRIPTC_SAN=1 pnpm test # sanitized lane
Corpus programs are differential tests against Node: every program runs under Node and as a compiled native binary, and stdout, stderr, and exit codes must match byte-for-byte. A new feature lands with corpus programs that pin its behavior both ways.
Name a new corpus program after what it tests, without a number: lowercase words joined by hyphens, such as `tests/corpus/intersection-restated-members.ts`, or a directory such as `tests/corpus/<name>/main.ts` for a multi-file program. Parallel changes kept taking the same next number; with names, two changes collide only when they add the same name, which git reports as a conflict. Leave existing numbered programs as they are: never rename or renumber them, and name a new program even when it extends a numbered family.
Record a new or remeasured program's CI cost (used to balance the test shards) in `tests/harness/corpus-costs/<program>.json`, not in `tests/harness/corpus-costs.json`; see the README there.
Before opening a PR that adds or changes corpus, diagnostic, or frontend fixtures, run `pnpm test:ts7 --baselines-only`. This fast completeness check uses the same fixture discovery as the parity suite; it does not type-check or replace behavioral parity. Generate missing preflight/order baselines, review their diagnostics and module order, and run the affected `order-parity.test.ts` batches before pushing. Keep existing baseline entries unchanged unless the corresponding behavior intentionally changes. The full `pnpm test:ts7` command also checks completeness before starting its sweep.
+36 -2
View File
@@ -6,6 +6,42 @@ All notable changes to scriptc will be documented in this file.
<!-- release:start -->
## 0.4.5
### Highlights
- **Fixes:**
- Release builds read a typed array's length without a header load that could read a freed view.
- `net.Socket` `write()` returns Node's backpressure boolean and fires `'drain'`.
- Super calls in JavaScript method values call the declared base method.
- Calling a non-function through an asserted callee throws Node's TypeError.
- **Faster programs:**
- Exceptions propagate by unwinding from directly called functions on Linux, instead of status checks after every call.
- Typed-array loops prove their bounds and keep their views disjoint in more cases, including views over shared memory in worker programs; integer loops stay in integers across nested counted loops, pure helper calls, powers of two and byte reads.
- Lone array callbacks run as loops with their bodies inlined, and row sums run two rows per pass.
- Number-key maps look keys up on their integer view and write updates through the entry the read found; small number-key maps use a direct index.
- Strings: base64 decodes eight characters at a time; Buffers fill, swap byte order and decode `utf16le` a word at a time; readline splits input in one scan; string scans over non-ASCII strings use their UTF-16 units.
- Untyped code: property caches also cache absent properties, object literal members go through the store caches, calls on plain arrays skip the method ladder, and dynamic values dispose without key-cache walks.
- JSON parses into discriminated unions, and dynamic values convert into nested unions, in one pass.
- BigInt division settles quotients from the top limbs, and limb shifts are vectorized.
- **Faster builds:**
- Function bodies are emitted on up to eight workers, including in dev builds, and repeated work in LLVM module emission is cut.
- Linux executables link with lld when the driver finds it, and unchanged executables are reused without selecting the runtime pack.
- Dev builds reuse their frontend output after edits that keep token positions, and unchanged frontend inputs are checked by file identity before hashing.
- Lowering fetches only the syntax trees it reads, and the large compiler tables are built on first use.
- Release builds of the native compiler use a profile collected on the release commit.
- Type checking can use a tsc-ts server shared by later builds (opt-in).
- **Node.js parity:**
- Crypto: RSA key generation lengths, RSA-PSS keys, encrypted private keys, `X509Certificate` fields and methods, and TLS certificates and `tls.Server` contexts.
- zlib: Brotli compression and decompression.
- Dates are mutable objects with Node's setters and conversions; URL hosts and paths parse as the URL Standard does, including non-ASCII hosts with UTS #46.
- `Math`, `JSON` and `Reflect` are real objects in JavaScript; objects can inherit from JavaScript class prototypes; typed arrays held as untyped values support named properties and `Symbol.species`.
- Error messages: `JSON.parse` syntax errors use V8's messages and positions; `Object.getPrototypeOf` of an Error answers `Error.prototype`.
- `util.inspect` of dynamic classes, functions and `%o` arguments, and `Symbol.toStringTag` fields and getters, match Node.
- **npm packages:** more npm and CommonJS dependencies compile statically, including namespace-style packages with guarded declarations and `var` exports, and untyped Maps, Sets and arrays are typed from their uses.
<!-- release:end -->
## 0.4.4
### Highlights
@@ -29,8 +65,6 @@ All notable changes to scriptc will be documented in this file.
- Split CommonJS `require` bindings, `__`-prefixed exports, string-key destructuring of `any` values, and record key order for values JavaScript built.
- **npm packages:** zod 4 and `@hono/zod-validator` values are projected at the declaration boundary.
<!-- release:end -->
## 0.4.3
### Highlights
+2
View File
@@ -18,6 +18,8 @@ The release job builds each pinned LLVM helper, precompiled runtime pack, and na
Release builds of the native CLI optimize the compiler with a profile collected on the release commit. The `cli-profile` job runs `node scripts/refresh-cli-profile.mjs` on Linux x64, which builds an instrumented compiler, runs it on tsc-ts, a slice of the corpus, and the runtime benchmark workloads, and writes the merged sparse profile. Every platform's CLI build uses that profile (`SCRIPTC_NATIVE_PROFILE_USE`), and the GitHub release attaches it as `scriptc-<version>-cli.profdata.gz`. Code the profile does not describe, or describes from older compiler sources, is optimized as without a profile. When the profile job fails, the CLI builds use the committed profile `packages/compiler/native/cli.profdata.gz`, which local and CI builds of the native compiler also use. Refresh the committed profile when compiler code has changed substantially since the last refresh: run `node scripts/refresh-cli-profile.mjs --tsc-ts <tsc-ts checkout>` on a quiet Linux x64 host and commit the new profile on its own.
Builds of the native compiler also order its functions by the committed layout `packages/compiler/native/cli.layout.gz`: the functions that `--version` and rebuilds of unchanged programs run come first, then the ones other builds run, ordered by the share of the layout's training builds that run each, so a run maps fewer pages of the executable. Functions the layout does not list keep their usual order. Function names of closures and generated helpers change with nearby edits, so the `cli-profile` job also collects a layout on the release commit (`scripts/refresh-cli-layout.mjs`, reusing the job's instrumented compiler), and the CLI builds use it (`SCRIPTC_NATIVE_LAYOUT`). Refresh the committed layout the same way as the profile, with `node scripts/refresh-cli-layout.mjs`, and commit it on its own.
Publishing uses npm trusted publishing (OIDC) — there is no npm token secret.
Each published package must have a GitHub Actions trusted publisher for
`release.yml` and the `Release` environment. A missing configuration fails
+3
View File
@@ -16,6 +16,7 @@ Application-shaped workloads for measuring the speed of compiled executables. Ea
| `dynamic-methods` | cpu | untyped JavaScript calling builtin methods on values it does not type: string `slice`/`indexOf`/`toUpperCase`/`padStart`, array `push`/`pop`/`includes`, `Map` and `Set`, and an object's own methods |
| `dynamic-properties` | cpu | untyped JavaScript reading and writing properties of values it does not type: records built by object literals in two key orders, nested records, and instances of a class and its subclass |
| `functional-pipeline` | cpu | `filter`/`map`/`reduce`/`flatMap` chains, closures, small records |
| `handler-tables` | cpu | dispatch tables of functions: `Record<string, fn>` read as `t[k]!(…)`, `t[k]?.(…)` and through a checked local, a `Map<string, fn>`, an array of handlers, and an object literal of methods; some handlers declare fewer parameters than the table type |
| `intern-table`, `intern-table-map`, `intern-table-1`, `intern-table-map-1` | cpu | worker threads interning the same type-like objects under string keys and records under number keys, then hits and misses: one shared `InternTable` per kind of key, or a module-level `Map` per thread (the `-map` entries), with 8 threads or 1 (the `-1` entries); under Node.js every thread has its own tables |
| `json-records` | cpu | `JSON.stringify`, typed `JSON.parse`, Map aggregation |
| `json-unions` | cpu | `JSON.parse` into discriminated unions: an event log with eight kinds and nested expression trees with nine, evaluated after the cast |
@@ -30,7 +31,9 @@ Application-shaped workloads for measuring the speed of compiled executables. Ea
| `record-boundaries` | cpu | records built from unchecked array reads passed to and returned from annotated functions |
| `records-sort` | cpu | comparator sorts, group-by, `reduce`/`filter` |
| `regex-logs` | cpu | regex `exec` with groups, `test`, global `replace` |
| `regex-replacers` | cpu | regex `replace`/`replaceAll` with inline callbacks whose parameters have no annotations: dictionary placeholders, snake_case to camelCase, date reordering, optional captures, capitalization, and a string search that reads the offset |
| `region-builds` | cpu | a watch-mode build loop over `LifetimeRegion`: each build binds a program in a new region and releases the previous one, which a cache keeps referenced for two builds |
| `string-iteration` | cpu | code point iteration over text that mixes ASCII, Latin-1 letters, CJK and emoji: a for-of word tokenizer, spread reversal, and `Array.from` over words |
| `template-render` | cpu | template literals, escaping, `map`/`join` |
| `throw-chains` | cpu | exceptions caught 2, 5 and 20 recursive calls above the throw, through direct calls and through a callback, and a backtracking parser that throws on a failed alternative |
| `thread-slots`, `thread-slots-cache` | cpu | worker threads reading one published type graph from an `InternTable` and keeping per-thread state for each type they visit: a `ThreadSlots` family, or a direct-mapped cache by id in front of a `Map` by id (the `-cache` entry); under Node.js both are per thread |
@@ -0,0 +1,6 @@
{
"entry": "workloads/handler-tables.ts",
"args": [
"4"
]
}
@@ -0,0 +1,108 @@
// Dispatch tables of functions: a `Record<string, fn>` of opcode handlers
// called as `ops[name]!(…)`, `ops[name]?.(…)` and through a checked local,
// a `Map<string, fn>` of the same handlers, an array of handlers indexed by
// opcode number, and an object literal of methods. Some handlers declare
// fewer parameters than the table's function type.
type Op = (acc: number, arg: number) => number;
const ops: Record<string, Op> = {
add: (acc, arg) => acc + arg,
sub: (acc, arg) => acc - arg,
mul: (acc, arg) => (acc * arg) % 1000003,
neg: (acc) => -acc,
half: (acc) => Math.floor(acc / 2),
mix: (acc, arg) => (acc ^ arg) & 0xffff,
};
const byName = new Map<string, Op>(Object.entries(ops));
const byCode: Op[] = Object.values(ops);
const names = Object.keys(ops);
const methods = {
add(acc: number, arg: number): number {
return acc + arg;
},
sub(acc: number, arg: number): number {
return acc - arg;
},
mul(acc: number, arg: number): number {
return (acc * arg) % 1000003;
},
};
interface Insn {
name: string;
code: number;
arg: number;
}
function program(length: number): Insn[] {
const out: Insn[] = [];
let seed = 12345;
for (let i = 0; i < length; i++) {
seed = (seed * 1103515245 + 12345) % 2147483648;
const code = seed % (names.length + 1);
// One in seven instructions names an opcode no table holds.
out.push({ name: code < names.length ? names[code]! : "nop", code, arg: (seed >> 8) % 97 });
}
return out;
}
function runAsserted(insns: Insn[]): number {
let acc = 1;
for (const insn of insns) if (insn.name !== "nop") acc = ops[insn.name]!(acc, insn.arg);
return acc;
}
function runOptional(insns: Insn[]): number {
let acc = 1;
for (const insn of insns) acc = ops[insn.name]?.(acc, insn.arg) ?? acc + 1;
return acc;
}
function runChecked(insns: Insn[]): number {
let acc = 1;
for (const insn of insns) {
const handler = ops[insn.name];
if (handler) acc = handler(acc, insn.arg);
}
return acc;
}
function runMap(insns: Insn[]): number {
let acc = 1;
for (const insn of insns) {
const handler = byName.get(insn.name);
if (handler !== undefined) acc = handler(acc, insn.arg);
}
return acc;
}
function runArray(insns: Insn[]): number {
let acc = 1;
for (const insn of insns) if (insn.code < byCode.length) acc = byCode[insn.code]!(acc, insn.arg);
return acc;
}
function runMethods(insns: Insn[]): number {
let acc = 1;
for (const insn of insns) {
if (insn.code === 0) acc = methods.add(acc, insn.arg);
else if (insn.code === 1) acc = methods.sub(acc, insn.arg);
else if (insn.code === 2) acc = methods["mul"](acc, insn.arg);
}
return acc;
}
const rounds = Number(process.argv[2] ?? "4");
const insns = program(200_000);
const totals = [0, 0, 0, 0, 0, 0];
for (let round = 0; round < rounds * 10; round++) {
totals[0] = (totals[0]! + runAsserted(insns)) % 1e9;
totals[1] = (totals[1]! + runOptional(insns)) % 1e9;
totals[2] = (totals[2]! + runChecked(insns)) % 1e9;
totals[3] = (totals[3]! + runMap(insns)) % 1e9;
totals[4] = (totals[4]! + runArray(insns)) % 1e9;
totals[5] = (totals[5]! + runMethods(insns)) % 1e9;
}
console.log(totals.join(" "));
@@ -0,0 +1,6 @@
{
"entry": "workloads/regex-replacers.ts",
"args": [
"1"
]
}
@@ -0,0 +1,60 @@
// Regex replace and replaceAll with inline callbacks, written as they
// usually are, without parameter annotations: template placeholders looked
// up in a dictionary, snake_case to camelCase, date reordering, optional
// version parts, capitalization and a string search with its offset.
let seed = 7;
function random(): number {
seed = (Math.imul(seed, 1103515245) + 12345) >>> 0;
return seed / 4294967296;
}
function pick<T>(items: readonly T[]): T {
return items[Math.floor(random() * items.length)]!;
}
const words = ["user", "order", "item", "cart", "price", "total", "status", "created", "updated", "id"];
const names = ["Ada", "Grace", "Linus", "Barbara", "Ken", "Margaret"];
const vars: Record<string, string> = {
name: "world",
city: "Lisbon",
day: "Tuesday",
plan: "pro",
count: "12",
};
const keys = [...Object.keys(vars), "missing"];
const scale = Number(process.argv[2] ?? "1");
const count = Math.floor(20000 * scale);
const templates: string[] = [];
const identifiers: string[] = [];
const dates: string[] = [];
const versions: string[] = [];
const sentences: string[] = [];
for (let i = 0; i < count; i++) {
templates.push(`Hello {${pick(keys)}}, your {${pick(keys)}} plan renews on {${pick(keys)}} in {${pick(keys)}}.`);
identifiers.push(`${pick(words)}_${pick(words)}_${pick(words)}${random() < 0.5 ? "_" + pick(words) : ""}`);
const year = 1990 + Math.floor(random() * 40);
const month = String(1 + Math.floor(random() * 12)).padStart(2, "0");
const day = String(1 + Math.floor(random() * 28)).padStart(2, "0");
dates.push(`from ${year}-${month}-${day} to ${year + 1}-${month}-${day} (${pick(names)})`);
versions.push(`v${i % 9}.${i % 13}${random() < 0.5 ? "." + (i % 7) : ""} and v${i % 5}.${i % 3}`);
sentences.push(`${pick(names)} said the ${pick(words)} and the ${pick(words)} were ready for ${pick(names)}`);
}
let length = 0;
let checksum = 0;
for (let round = 0; round < 4; round++) {
for (let i = 0; i < count; i++) {
const filled = templates[i]!.replace(/\{(\w+)\}/g, (_m, key) => vars[key] ?? `<${key}>`);
const camel = identifiers[i]!.replace(/_([a-z])/g, (_m, c) => c.toUpperCase());
const reordered = dates[i]!.replace(/(\d{4})-(\d{2})-(\d{2})/g, (_m, y, m, d) => `${d}/${m}/${y}`);
const padded = versions[i]!.replace(/v(\d+)\.(\d+)(?:\.(\d+))?/g, (_m, major, minor, patch) => `v${major}.${minor}.${patch ?? "0"}`);
const titled = sentences[i]!.replace(/\b[a-z]/g, (c) => c.toUpperCase());
const marked = sentences[i]!.replaceAll("the", (m, at) => (at % 2 === 0 ? m.toUpperCase() : m));
length += filled.length + camel.length + reordered.length + padded.length + titled.length + marked.length;
checksum = (checksum * 31 + camel.charCodeAt(camel.length - 1) + padded.charCodeAt(padded.length - 1)) >>> 0;
}
}
console.log(templates[0]!.replace(/\{(\w+)\}/g, (_m, key) => vars[key] ?? `<${key}>`));
console.log(identifiers[1]!.replace(/_([a-z])/g, (_m, c) => c.toUpperCase()));
console.log(versions[2]!.replace(/v(\d+)\.(\d+)(?:\.(\d+))?/g, (_m, major, minor, patch) => `v${major}.${minor}.${patch ?? "0"}`));
console.log("length", length, "checksum", checksum);
@@ -0,0 +1,6 @@
{
"entry": "workloads/string-iteration.ts",
"args": [
"1"
]
}
@@ -0,0 +1,59 @@
// Code point iteration over mixed text: a word tokenizer over for-of, a
// character histogram, reversal through spread, and Array.from over
// words. The text mixes ASCII, Latin-1 letters, CJK and emoji.
let seed = 11;
function random(): number {
seed = (Math.imul(seed, 1103515245) + 12345) >>> 0;
return seed / 4294967296;
}
const pieces = [
"the", "quick", "brown", "fox", "jumps", "over", "lazy", "dog",
"café", "naïve", "über", "señor", "straße", "déjà", "vu",
"日本", "語", "テキスト", "中文", "한국어",
"😀", "🚀", "👍", "🎉",
];
const punctuation = [" ", " ", " ", ", ", ". ", "! ", "\n"];
const scale = Number(process.argv[2] ?? "1");
const lines: string[] = [];
for (let i = 0; i < Math.floor(4000 * scale); i++) {
let line = "";
const words = 6 + Math.floor(random() * 10);
for (let w = 0; w < words; w++) {
line += pieces[Math.floor(random() * pieces.length)]!;
line += punctuation[Math.floor(random() * punctuation.length)]!;
}
lines.push(line);
}
function isWordChar(c: string): boolean {
const code = c.codePointAt(0)!;
return (code >= 0x61 && code <= 0x7a) || (code >= 0x41 && code <= 0x5a) || code >= 0xc0;
}
let tokens = 0;
let tokenUnits = 0;
let reversedLength = 0;
let fromLength = 0;
const histogram = new Map<string, number>();
for (let round = 0; round < 30; round++) {
for (const line of lines) {
let word = "";
for (const c of line) {
if (isWordChar(c)) {
word += c;
continue;
}
if (word !== "") {
tokens++;
tokenUnits += word.length;
if (round === 0) histogram.set(word, (histogram.get(word) ?? 0) + 1);
fromLength += Array.from(word).length;
word = "";
}
}
reversedLength += [...line].reverse().join("").length;
}
}
const top = [...histogram].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)).slice(0, 5);
console.log(top.map(([word, count]) => `${word}:${count}`).join(" "));
console.log("tokens", tokens, "units", tokenUnits, "reversed", reversedLength, "from", fromLength);
+65 -2
View File
@@ -2,7 +2,7 @@
title: "CLI Reference"
---
The `scriptc` command has five subcommands: `build`, `run`, `coverage`, `cache warm`, and `merge-profiles`. `scriptc --help` prints this summary and the options below, and `scriptc --version` prints the installed version.
The `scriptc` command has six subcommands: `build`, `run`, `coverage`, `types`, `cache warm`, and `merge-profiles`. `scriptc --help` prints this summary and the options below, and `scriptc --version` prints the installed version.
```console
$ scriptc --help
@@ -21,6 +21,13 @@ Usage:
exporting the profile symbols; a profile
with a sidecar section also gets the
contract sidecar JSON beside the archive
scriptc types patch <package> <selector> <type> [--range <r>] [--dry-run]
fix a wrong declaration of an installed
package: shows what the selector
matches and adds the type patch to
package.json ("| undefined" widens)
scriptc types list the project's type patches and what
they match
scriptc cache warm [runtime|tls…] verify and load precompiled runtime families
for the current compiler/SDK/target
scriptc merge-profiles -o <out.profdata> [--sparse] <profile…>
@@ -88,6 +95,24 @@ $ scriptc run fib.ts
Analyzes the program without building it and reports what compiles and what blocks the rest. See [Coverage Reports](/docs/coverage).
## scriptc types
Writes and lists [type patches](/docs/dependencies#fix-a-packages-types), the project's fixes for wrong declarations of npm packages.
<dl>
<dt><code>scriptc types patch &lt;package&gt; &lt;selector&gt; &lt;type&gt;</code></dt>
<dd>Finds the package installed for the working directory, prints every declaration the selector matches in its declaration files, its JSDoc and its <code>@types/</code> package with the type before and after, and adds the patch to the nearest <code>package.json</code>. The patch joins an entry whose range covers the installed version, or gets the range <code>^&lt;installed version&gt;</code>. Nothing is written when the selector matches nothing. <code>--range &lt;range&gt;</code> chooses the range, and <code>--dry-run</code> only prints.</dd>
<dt><code>scriptc types list</code></dt>
<dd>Prints each type patch in the nearest <code>package.json</code>, whether it applies to the installed version, and what it matches.</dd>
</dl>
```console
$ scriptc types list
commander@^15.0.0
HelpContext.helpWidth: | undefined
node_modules/commander/lib/command.js:2481 number -> number | undefined
```
## scriptc cache warm
Verifies and loads the installed precompiled runtime objects and vendored libraries, and prints the cache directory. Pass `runtime`, `tls`, or both to select which to warm. Ordinary builds don't need this step. With `--sanitize`, it builds the instrumented runtime objects using a C toolchain.
@@ -138,11 +163,14 @@ With `--sparse`, the profile leaves out the functions the runs never reached. Th
<dt><code>--target-cpu &lt;baseline|x86-64-v2|x86-64-v3|x86-64-v4|native&gt;</code></dt>
<dd>On x86-64 targets, compile the program's code for an x86-64 microarchitecture level. The default, <code>baseline</code>, runs on any x86-64 CPU. A higher level lets LLVM use more instructions, and the executable then runs only on CPUs that support that level. <code>native</code> uses the highest level the build machine supports. Valid for executable, assembly, and object output on x86-64 targets. See <a href="#target-cpu">Target CPU</a>.</dd>
<dt><code>--cpu-dispatch</code></dt>
<dd>On x86-64 targets, compile the program's code twice, for the baseline and for <code>x86-64-v3</code>, and choose the copy when the program starts. The executable runs on any x86-64 CPU and uses the <code>x86-64-v3</code> code on CPUs that support it. Not used with a <code>--target-cpu</code> level above <code>baseline</code>. Valid only for executable builds. See <a href="#runtime-cpu-dispatch">Runtime CPU dispatch</a>.</dd>
<dt><code>--profile-generate &lt;pattern&gt;</code></dt>
<dd>On Linux, build an instrumented executable for profile-guided optimization. Each run writes a raw profile to the path pattern, where <code>%p</code> expands to the process ID; the <code>LLVM_PROFILE_FILE</code> environment variable overrides the pattern at run time. A relative pattern resolves from the current working directory. Instrumented programs run slower. Valid only for executable builds with <code>--optimization=release</code> or <code>speed</code>.</dd>
<dt><code>--profile-use &lt;file.profdata&gt;</code></dt>
<dd>Optimize the executable with a profile from <code>scriptc merge-profiles</code>: code is laid out, inlined, and split by how the profiled runs used it. Code the profile does not describe, or describes from an older version of the program, is optimized as without a profile, so a stale profile only loses part of its gain. A new or changed profile compiles every partition of the program again. Valid only for executable builds with <code>--optimization=release</code> or <code>speed</code>.</dd>
<dd>Optimize the executable with a profile from <code>scriptc merge-profiles</code>: code is laid out, inlined, and split by how the profiled runs used it. Code the profile does not describe, or describes from an older version of the program, is optimized as without a profile, so a stale profile only loses part of its gain. A new or changed profile compiles every partition of the program again. <code>scriptc build</code> prints how the profile matched the program's functions on stderr; see <a href="#profile-guided-optimization">Profile-guided optimization</a>. Valid only for executable builds with <code>--optimization=release</code> or <code>speed</code>.</dd>
<dt><code>--npm-static &lt;pkg[,pkg…]|auto&gt;</code></dt>
<dd>Name npm packages to compile even if they don't ship their own type declarations (repeatable). A trailing <code>...</code>, as in <code>fs-extra...</code>, also names every package that package depends on. <code>auto</code> uses the default automatic selection. Packages that can't compile produce diagnostics. See <a href="/docs/dependencies#explicit-package-selection">npm Dependencies</a>.</dd>
@@ -234,6 +262,25 @@ $ scriptc build app.ts --optimization=speed --profile-use app.profdata
Train on workloads like the ones the program will run: code the training never reached is optimized as without a profile. The profile can be committed and reused as the program changes. Functions whose control flow changed since the profile was collected lose their profile, and the rest keep theirs, so regenerate it when much of the program has changed. [Build parallelism](/docs/how-it-works#build-parallelism) describes what a profile adds to build time.
`scriptc build --profile-use` prints one line on stderr with how the profile matched the program's functions:
```
scriptc: profile app.profdata: 9170 functions annotated, 0 mismatched, 28636 without a record
```
- **annotated:** functions optimized with the profile's counts.
- **mismatched:** functions whose control flow changed since the profile was collected. They are optimized without counts.
- **without a record:** functions the profile does not describe: new functions, and functions the profiled runs never reached.
- When the build reuses cached partitions whose counts were not recorded, the line ends with the number of those partitions.
When more than 10% of the functions the profile describes (annotated and mismatched) are mismatched, the build also prints a warning:
```
scriptc: warning: 3739 of the 8947 functions app.profdata describes (41.8%) changed since it was collected and are optimized without their counts; collect the profile again
```
The build still succeeds. Collecting the profile again with the current program and scriptc version restores the counts.
## Target CPU
By default, x86-64 executables run on any x86-64 CPU, so the compiler uses only the baseline instruction set (SSE2). `--target-cpu` compiles the program's code for a higher x86-64 microarchitecture level. Each level includes the ones below it:
@@ -271,6 +318,22 @@ An executable built for a level runs only on CPUs that support that level. On an
The level applies to the program's own code. The runtime pack keeps its baseline code. Builds for different levels never share cached artifacts, and `baseline` builds are the same as builds without the option.
### Runtime CPU dispatch
`--cpu-dispatch` keeps the executable portable and still uses the higher level where the CPU has it. The program's functions are compiled for the baseline and for `x86-64-v3`. At startup, the executable checks the CPU and the operating system's register support, and then runs the `x86-64-v3` code on CPUs that support every feature of that level. Calls between the program's functions stay within the chosen copy.
```console
$ scriptc build app.ts --optimization=speed --cpu-dispatch -o app
```
The second copy makes the executable larger and the first build of the program slower, since LLVM compiles the program's code twice. Unchanged rebuilds are not affected. Both copies compute the same results: neither contracts floating-point operations into fused multiply-adds.
The `SCRIPTC_CPU_LEVEL` environment variable caps the level the executable uses, for example to test the baseline code on a newer machine. It takes a level from `0` to `4`, `baseline`, or a level name such as `x86-64-v3`; any other value selects the baseline code.
```console
$ SCRIPTC_CPU_LEVEL=baseline ./app
```
## LLVM backend
scriptc generates LLVM IR and compiles it to native code. Executable builds link the result with the matching precompiled runtime pack. Use <code>--emit=llvm</code> to inspect the generated code.
+1 -1
View File
@@ -245,7 +245,7 @@ $ scriptc build scale.ts
1 error.
```
A copy such as `slice()` or a spread is checked as if it were the same array as its source. The results of callbacks are not followed, so an array built by `map` or `Array.from` with a mapping function cannot be `Int32[]`; build it with a loop that stores `value | 0`. scriptc refuses an `Int32[]` slot whose array can come from code it cannot see, such as `JSON.parse`, dynamic values or the callers of a function used as a value, and an array that can reach one and escapes to such code, such as a call through a function value (SC7003).
A copy such as `slice()` or a spread is checked as if it were the same array as its source. The results of a callback are followed only when scriptc copies it into the loop that runs the array method: a callback written at a `map` or `filter` call whose captured variables are not reassigned, such as `xs.map((x) => (x * 2) | 0)`. Other callback results are not followed, so for example an array built by `Array.from` with a mapping function cannot be `Int32[]`; build it with a loop that stores `value | 0`. scriptc refuses an `Int32[]` slot whose array can come from code it cannot see, such as `JSON.parse`, dynamic values or the callers of a function used as a value, and an array that can reach one and escapes to such code, such as a call through a function value (SC7003).
## Immutable
+69
View File
@@ -141,6 +141,75 @@ CommonJS packages compile with Node.js's module semantics. Each `require()` eval
A JavaScript package can contain operations scriptc can't compile, often in functions your program never calls. These don't fail the build: each one compiles to code that throws a runtime error if it ever runs. Coverage reports list them as deferred sites, so review the list and test the parts of the package your program uses. Sites in a module's top-level code are listed under `runs at startup`: that code runs when the module loads, at startup for a module the program imports.
## Fix a package's types
scriptc trusts declared types: a package's `.d.ts` files, its `@types/` package, and the JSDoc types in its JavaScript. A value that contradicts its declared type throws a `TypeError` instead of flowing on, so a package whose declarations are wrong can stop a program that runs under Node.js. A common case is a member declared `string` or `number` that is sometimes `undefined`.
When the type comes from a package's declarations, the error names the declaration and the patch that would admit the value:
```text
Uncaught TypeError: expected string at $, got undefined
profilekit@3.1.0 declares Profile.email as string (index.d.ts:7)
if that declaration is wrong, patch it: scriptc types patch profilekit "Profile.email" "| undefined"
```
Fix such a declaration in your project with a type patch. `scriptc types patch` shows what a declaration path matches in the installed package and adds the patch to your `package.json`:
```console
$ scriptc types patch commander "HelpContext.helpWidth" "| undefined"
commander 15.0.0 (node_modules/commander)
lib/command.js:2481 number -> number | undefined
wrote package.json scriptc.typePatches["commander@^15.0.0"].declarations["HelpContext.helpWidth"]
```
The patch it writes looks like this:
```json:package.json
{
"scriptc": {
"typePatches": {
"commander@^15.0.0": {
"declarations": {
"HelpContext.helpWidth": "| undefined"
}
}
}
}
}
```
Each key names a package and a semver range of the installed versions the patch describes. `declarations` maps a declaration to a type:
<dl>
<dt>`"| undefined"`</dt>
<dd>A type that starts with `|` widens the declared type, here to `number | undefined`.</dd>
<dt>`"string | null"`</dt>
<dd>Any other type replaces the declared type.</dd>
</dl>
A declaration is named by its path: `Options.name` for a member of a type, `parse()` for a function's return type, `parse(text)` for a parameter, `list()[]` for an array's elements, and `Env[string]` for an index signature. `export=()` names the return type of the function the module exports, `default` its default export, and a file prefix such as `index.js:parse()` names a declaration inside one of the package's files. One patch applies to the package's own declarations, its JSDoc, and its `@types/` package. The patched type then holds everywhere, so your code has to handle the `undefined` that a widened declaration allows. An optional `"note"` string can link the upstream issue.
For larger fixes, replace a whole declaration file, or give a package without declarations its own:
```json:package.json
{
"scriptc": {
"typePatches": {
"some-client@^3.2.0": {
"files": { "dist/types/options.d.ts": "./type-patches/options.d.ts" }
},
"untyped-helper@1.x": {
"types": "./type-patches/untyped-helper.d.ts"
}
}
}
}
```
`files` maps a declaration file inside the package, or inside its `@types/` package written as `@types/<name>/<path>`, to a local `.d.ts` file. `types` supplies the package's declaration entry. Paths of local files are relative to the `package.json`, and a replaced file can import the package's other declaration files with the same relative paths as the file it replaces.
Patches change only declarations, never the package's code, and values are still checked against the patched types. A build warns when a patch doesn't apply as written: when no range covers the installed version, when a declaration path matches nothing, when the declaration already has the type, or when a path is ambiguous. Report wrong declarations to the package too, so the patch can be removed later.
## Provenance sources (experimental)
`--provenance-sources` compiles a package from the source at the commit its npm provenance attestation names, instead of from its published JavaScript. This lets packages written in TypeScript compile from their original TypeScript. Packages without a usable attestation compile from their installed files as usual.
+2
View File
@@ -52,6 +52,8 @@ title: "Limitations"
<include>../limitations/types-and-class-definitions/static-field-updates.mdx</include>
<include>../limitations/types-and-class-definitions/array-subclasses.mdx</include>
<include>../limitations/types-and-class-definitions/local-class-expressions.mdx</include>
<include>../limitations/types-and-class-definitions/constructor-function-inheritance.mdx</include>
@@ -31,22 +31,25 @@
`checkPrime`, `checkPrimeSync`, `generatePrime`, and `generatePrimeSync` support bigint, ArrayBuffer, typed-array, Buffer, and DataView values and the `checks`, `safe`, `add`, `rem`, and `bigint` options on native targets, with Node's errors; the callback forms compute before they return and call back in a later macrotask.
Candidates and sizes longer than 262144 bits throw a coded SC2020 error, and wasm32-wasi builds are refused.
Node calls their callbacks with `undefined` as the error, which a callback whose error parameter is typed `Error | null`, as @types/node declares it, receives as `null`.
RSA, EC, Ed25519, and X25519 private and public KeyObjects come from `generateKeyPairSync`, `generateKeyPair`, `createPrivateKey`, and `createPublicKey`, on native targets.
RSA, RSA-PSS, EC, Ed25519, and X25519 private and public KeyObjects come from `generateKeyPairSync`, `generateKeyPair`, `createPrivateKey`, and `createPublicKey`, on native targets.
`generateKeyPairSync` and `generateKeyPair` check their arguments in Node's order, with Node's errors, including the OpenSSL errors for RSA modulus lengths below 512 or above 2147483647 bits and for public exponents of 0, 1, or an even number, which `generateKeyPair` passes to its callback.
RSA keys generate with even modulus lengths from 1024 to 8192 bits and public exponents up to 2147483647; other lengths and exponents that Node accepts, and `paramEncoding: 'explicit'`, throw a coded SC2020 error.
RSA keys generate with modulus lengths from 512 to 8192 bits, an odd length from 2048 bits yielding one bit less as in Node, and odd public exponents up to 4294967295; longer moduli that Node accepts, and `paramEncoding: 'explicit'`, throw a coded SC2020 error.
The EC curves are prime256v1 (P-256), secp384r1 (P-384), secp521r1 (P-521), and secp256k1.
Keys read and write PEM and DER as PKCS#1, SEC1, PKCS#8, and SubjectPublicKeyInfo, and JWK (Ed25519 and X25519 keys use PKCS#8, SubjectPublicKeyInfo, and JWK); `createPublicKey` also takes a private key or an X.509 certificate.
EC, Ed25519, and X25519 keys also read and write the `raw-public` and `raw-private` formats, including compressed EC points.
Raw X448, Ed448, and post-quantum keys, EC scalars of 0 or at least the curve order, and the EC point at infinity, which Node accepts, throw a coded SC2020 error.
They support `type`, `asymmetricKeyType`, `asymmetricKeyDetails`, `export()`, `equals()`, and `instanceof KeyObject`.
`crypto.sign`, `crypto.verify`, `createSign`, and `createVerify` support RSA PKCS#1 v1.5 and PSS padding and ECDSA with DER and IEEE P1363 encodings over SHA-1 and SHA-2 digests, and Ed25519 through `crypto.sign` and `crypto.verify` with a `null` or `undefined` algorithm.
RSA-PSS keys follow their RSASSA-PSS-params as Node does: PSS padding only, the key's digest and MGF1 digest, and salts of at least the key's length, with OpenSSL's errors; their details name the parameters, they export as PKCS#8 and SubjectPublicKeyInfo only, and digests other than SHA-1 and SHA-2 in their options throw a coded SC2020 error.
Ed25519 signing, verification, and private keys link when a string literal in the program names `ed25519` (in any case); without one they throw a coded SC2020 error, while Ed25519 public keys still import and export.
X509Certificate supports `publicKey`, `verify()`, `checkIssued()`, `checkPrivateKey()`, `checkHost()`, `checkEmail()`, `checkIP()`, `toLegacyObject()`, `toString()`, and `toJSON()`, and `String()`, template literals, and `+` give its PEM text as `toString()` does.
`publicKey`, `verify()`, and `checkPrivateKey()` are refused in wasm32-wasi builds, and an Ed25519 certificate's `verify()` needs the `ed25519` literal like the other Ed25519 operations.
Own-key walks over a certificate (`Object.keys()`, `Object.entries()`, spread, `for...in`, and `hasOwnProperty`) are refused, since Node keeps its fields as prototype getters.
`JSON.stringify()` and `console.log()` of a certificate, a certificate stored in an `unknown` or `any` slot, and its methods on a union-typed value are also refused.
Sign and Verify values accumulate `update()` data and are not writable streams.
Encrypted private keys (`passphrase`, `cipher`), the other key types (`rsa-pss`, `dsa`, `ed448`, `x448`, and the rest), and wasm32-wasi builds throw a coded SC2020 error or are refused.
Private keys export encrypted (`cipher`, `passphrase`) with aes-128, aes-192, and aes-256 in CBC and ECB modes and with des-ede3-cbc, PKCS#8 as PBES2 with PBKDF2-HMAC-SHA256 and PKCS#1 and SEC1 as traditional PEM, and the ciphers OpenSSL refuses for a form throw its errors; a cipher option can also be an OID; other ciphers Node encrypts with throw a coded SC2020 error.
Encrypted private keys import with a `passphrase` from PBES2 with HMAC-SHA PRFs and the CBC and ECB ciphers, and from traditional PEM with the CBC ciphers, with Node's errors for a missing or wrong passphrase; other schemes and ciphers throw a coded SC2020 error once a passphrase is given.
The other key types (`dsa`, `ed448`, `x448`, and the rest) and wasm32-wasi builds throw a coded SC2020 error or are refused.
Comparing keys of different types with `equals()` answers false; Node also leaves an OpenSSL error queued, which a later key operation can report.
`publicEncrypt`/`privateDecrypt` remain unsupported.
The WebCrypto `crypto` global, which node:crypto also exports as `webcrypto`, supports `randomUUID()` and `getRandomValues()`, also read as values from untyped JavaScript.
@@ -1,4 +1,8 @@
- **Globals:** Stored `globalThis` references support identity and probes for absent capabilities.
Most builtin members require direct global access; access through a stored global object can raise `SC2020`.
In JavaScript, reading a builtin global through the global object by name (`globalThis[name]`, or a stored global object) answers what the global's own spelling reads, and builtin module members that are global objects in Node, such as `require("buffer").atob` and `require("timers").setTimeout`, are the same values.
`WebAssembly` read this way, and builtin members read through a global object that untyped code received, can raise `SC2020`.
`for (key in globalThis)` visits Node's enumerable globals in Node's order, then the program's own global properties.
`navigator` answers Node's `hardwareConcurrency`, `language`, `languages`, `platform`, and `userAgent`, with `language` derived from `LC_ALL`, `LC_MESSAGES`, or `LANG` as Node does.
`navigator.locks` raises `SC2020`, as does `navigator.language` for a locale outside the `language_TERRITORY.codeset@modifier` form, or one whose language or territory needs ICU's tables (a three-letter territory, for example).
`Temporal` is not defined, as in Node.js 24: `typeof Temporal` is `"undefined"`, `globalThis.Temporal` is `undefined`, and any other use throws `ReferenceError: Temporal is not defined`.
Programs that name it type-check against TypeScript's `Temporal` declarations.
@@ -4,7 +4,13 @@
When an untyped value reaches `NodeJS.ReadableStream` or `NodeJS.WritableStream`, those two interfaces hold any value, so JavaScript stream objects (constructor-function streams, plain objects with `on` and `pipe`) pass through TypeScript functions typed with them and come back to JavaScript as the same objects.
Member calls on such a value use the native stream when it is one and call the object's own members otherwise; `readable.pipe()` into a JavaScript destination follows Node's pipe protocol.
The first `pipeline` stage may arrive as an untyped value that is a native stream, a `Cipheriv` or `Decipheriv` value, or an iterable: a string, an array, a generator object, or any value with a `Symbol.asyncIterator` or `Symbol.iterator` method, which the pipeline pumps into the next stage as Node does.
Later `pipeline` stages and `for await` sources that arrive as untyped values must be native streams, or `Cipheriv` and `Decipheriv` values, at run time; other values throw a not-supported error.
It may also be a source function, which the pipeline calls with `{ signal }` and whose iterable result it pumps, or a `{ readable, writable }` pair, whose readable side it pumps.
Later `pipeline` stages that arrive as untyped values may be native streams, `Cipheriv` and `Decipheriv` values, functions, and iterables.
A function is called with the previous stage and `{ signal }` as a function stage: before the last stage it must return an async iterable, and as the last stage it may return a promise, whose value resolves the pipeline, or an async iterable, which feeds the PassThrough that `pipeline()` returns.
An untyped source function, function stage, or destination that returns a stream is unsupported.
An iterable becomes `Duplex.from` of it, which the next stage reads from while the stages before it are not read, as in Node.
A pipeline branches at run time on whether each of its first three untyped stages after the first is a function; a function in a later untyped stage, an untyped web stream, and a `{ readable, writable }` pair after the first stage throw a not-supported error.
`for await` sources that arrive as untyped values must be native streams, or `Cipheriv` and `Decipheriv` values, at run time; other values throw a not-supported error.
Native streams expose no `emit` to JavaScript, so a JavaScript stream whose own `pipe()` emits on its destination (the legacy `Stream` pipe) cannot pipe into one.
`Readable.from` accepts strings, Buffers, arrays, Sets, Maps, Map and Set iterators, generators, async generators, and class iterables and async iterables, and in JavaScript any iterable or async iterable.
In JavaScript, a sync iterator value with a `then` method that is not a promise, and an object whose `[Symbol.asyncIterator]` or `[Symbol.iterator]` method is a generator method, are unsupported.
@@ -7,6 +7,7 @@ Some builtins can be stored and passed as functions:
In JavaScript, `setTimeout`, `setInterval`, `setImmediate`, `clearTimeout`, `clearInterval`, `clearImmediate`, `queueMicrotask`, and `process.nextTick` are function values wherever they are stored, including conditional and logical expressions and assignments: `typeof` answers `"function"`, identity holds across spellings, and calls schedule as the direct calls do, returning the same numeric timer handles.
Calls through these values bypass `node:test` mock timers.
In JavaScript, `atob`, `btoa`, and `structuredClone` are function values the same way, and calls through them run what the direct calls run.
Other builtin globals stored in JavaScript remain opaque identity values.
In JavaScript, `require("events")` and the `EventEmitter` class assigned to an untyped binding or stored in an object (`ReleaseEmitter = EventEmitter`) are the untyped `EventEmitter` constructor that constructor functions inherit from (see below): `new` through it builds such an emitter object, and identity and `instanceof` agree with the class.
A class can extend `require("events")` directly.
@@ -14,7 +15,7 @@ A class can extend `require("events")` directly.
Other immutable aliases of table-backed Node builtins support direct calls, but cannot be passed elsewhere.
`util.promisify` supports compile-time conversions of `child_process.execFile`, `child_process.exec`, `setTimeout` and `setImmediate` (to the `timers/promises` functions, as in Node), `stream.finished` and `stream.pipeline` (to the `stream/promises` functions, as in Node), the `zlib` callback one-shots `deflate`, `inflate`, `deflateRaw`, `inflateRaw`, `gzip`, `gunzip` and `unzip` (with or without options), the `crypto` callback functions `randomBytes`, `pbkdf2`, `scrypt`, `hkdf`, `randomFill`, `randomInt` and `generateKey`, `dns.lookup` (settling with `{ address, family }`, or the address array with `all: true`) and `dns.lookupService` (settling with `{ hostname, service }`), and the `fs` callback functions that have an `fs/promises` counterpart (`access`, `appendFile`, `chmod`, `chown`, `copyFile`, `lchown`, `link`, `lstat`, `lutimes`, `mkdir`, `mkdtemp`, `readFile`, `readdir`, `readlink`, `realpath`, `rename`, `rm`, `rmdir`, `stat`, `statfs`, `symlink`, `truncate`, `unlink`, `utimes`, and `writeFile`); calls through the converted function lower as the `fs/promises` call.
`util.promisify` over an untyped (`any`) function returns a native wrapper that follows Node's callback rules and carries the original's `name` and `length`.
`util.promisify` over an untyped function (a value typed `any`, a function whose parameters are untyped, or any other target in JavaScript) returns a native wrapper that follows Node's callback rules and carries the original's `name` and `length`, and throws Node's `ERR_INVALID_ARG_TYPE` for values that are not functions.
Such a function with other own properties, `util.promisify.custom` among them, throws `SC2020` where `util.promisify` runs, and the wrapper does not report Node's DEP0174 warning when the original returns a promise.
`util.styleText` supports standard formats and aliases, `#RGB` and `#RRGGBB` hex colors, arrays of formats, nested ANSI resets, and explicit color enabling with `{ validateStream: false }`.
@@ -1,6 +1,13 @@
`console.log`, `info`, and `debug` write to stdout; `error` and `warn` write to stderr.
They accept `unknown`, printing strings verbatim and other values through native `util.inspect`.
Direct calls support global `console` and `node:console` imports.
Console output, `util.format`, and `util.formatWithOptions` with a format string known only at run time, spread arguments, or an options object format their arguments at run time.
There, `%s` of a function or of a class instance whose class defines `toString` and `%o` of an object throw `SC2020`.
`util.inspect` with `colors`, with option values known only at run time, or in the `inspect(value, showHidden, depth, colors)` form renders the value's untyped view in the runtime with Node's styles.
Colored output of errors, promises, regular expressions, `DataView`, `ArrayBuffer`, weak collections, iterators, and other native objects throws `SC2020`.
Inspect options other than `depth`, `colors`, `customInspect`, `compact` (a number or `false`), `breakLength`, and `sorted` (a boolean) throw `SC2020` when they are set to a value other than Node's default.
`util.inspect` calls `[util.inspect.custom]` methods of classes and objects with Node's depth, options, and `util.inspect` arguments, and `console.dir` and `customInspect: false` skip them.
A class instance with such a method that is held as an untyped value throws `SC2020` when it is inspected, and a class whose subclasses declare the method without declaring it itself is refused.
Stored global console values and detached output methods retain identity and accept ordinary arguments.
Stored methods do not support format specifiers with substitution arguments.
Other stored console APIs, custom `Console` instances, and console mutation are unsupported.
+1 -1
View File
@@ -1,7 +1,7 @@
[Contract types](/docs/contracts) are checked only where they are written as the annotation of a parameter, variable, class instance field or function result, `Acyclic` only on classes, interfaces and object type aliases, and `ProgramLifetime` only in the `implements` clause of a class declaration; other aliases, interface members and nested type positions are reported.
In programs that use worker threads, a surrounding `try`/`catch` does not discharge `NoThrow`.
`Int32` refuses parameters of functions used as values and fields of classes whose instances are stored in `any` or `unknown` values.
`Int32[]` refuses arrays that can come from or escape to code scriptc cannot see, does not follow callback results (such as `map` results), and checks a copy made by `slice` or a spread as if it were its source array.
`Int32[]` refuses arrays that can come from or escape to code scriptc cannot see, follows callback results only for callbacks written at a `map` or `filter` call that scriptc runs inline, and checks a copy made by `slice` or a spread as if it were its source array.
Element reads that find a value are int32s, but a scalar `Int32` slot still needs `a[i] | 0`, because a read can miss and produce `undefined`.
`Immutable` refuses values stored in `any` or `unknown` or that another reference can still change.
`ProgramLifetime` applies to root classes of executables only; instances the program drops are never reclaimed unless they belong to a released [lifetime region](/docs/experimental#lifetimeregion).
+12 -6
View File
@@ -2,12 +2,18 @@ Node-API (N-API) and V8 `.node` addons depend on Node.js itself, so compiled pro
Direct `createRequire` calls to local addons are rejected at compile time.
A package that requires an addon needs a JavaScript implementation that compiles, or a replacement through native FFI.
A package that looks for an optional addon at run time compiles with `--npm-static` when the lookup is inside a `try` block.
There, a `createRequire` require call with a computed specifier, and a `require.resolve` or `require.resolve.paths` call with a computed request, evaluate their arguments and then throw an error.
Its `require.resolve` read as a value is a function that throws when called.
Coverage lists these as deferred to runtime.
The package's `catch` clause then runs as it does in Node.js when the addon is missing.
Outside a `try` block, the same uses keep the package refused.
A package that looks for an optional addon at run time compiles with `--npm-static`.
In JavaScript dependencies, a `createRequire` require call with a computed specifier, and `require.resolve` called with a computed request or read as a value, resolve the specifier with the Node.js algorithm when the program runs.
`require.resolve` returns the path Node.js returns.
When nothing resolves, both throw the `MODULE_NOT_FOUND` error that Node.js throws, so a package that probes for a missing addon takes the same branch as in Node.js.
When the specifier of a require call resolves to a native addon, a builtin, or a file that is not part of the compiled program, the program prints an SC2020 error that names it and exits with status 1, because Node.js would load that module.
A `catch` clause around the call does not run in that case.
Resolution steps that the runtime does not reproduce, such as package `imports` specifiers, `require.resolve` options, and subpaths that a package does not export, end the program the same way.
Coverage lists these calls as deferred to runtime.
Other computed uses compile when they are inside a `try` block: a require call with spread arguments, a `require.resolve` call with another argument count, and `require.resolve.paths` called with a computed request evaluate their arguments and then throw an error, and `require.resolve.paths` read as a value is a function that throws when called.
Coverage lists these as deferred to runtime as well, and the package's `catch` clause then runs as it does in Node.js when the addon is missing.
Outside a `try` block, these uses keep the package refused.
This applies until compiled programs can load addons through Node.js.
Use [Native FFI](/docs/ffi#replacing-a-node-api-addon) to call a plain C ABI function linked from an object or static archive.
The guide includes a replacement for a small Node-API helper.
@@ -25,3 +25,10 @@ Index-signature records list declared fields before the other keys.
Optional fields and properties added through a record's `unknown` view can be deleted.
A required field has no absent state, so deleting it through the view throws `TypeError: Cannot delete property 'x' of #<Object>` and leaves the record unchanged, where Node.js removes the property.
Records inherit `toString`, `toLocaleString`, `valueOf`, `hasOwnProperty`, `isPrototypeOf` and `propertyIsEnumerable` from `Object.prototype`.
A call of one of these methods by name runs the built-in with the record as its receiver, unless the record holds an own function under that name.
A keyed read such as `handlers[name]` of a record whose values are functions answers the built-in when the record lacks the key, so truthiness, `typeof` and calls match Node.js.
A keyed read of a record whose values are not functions, such as `counts["toString"]` on a `Record<string, number>`, answers `undefined` where Node.js answers the inherited function, so `counts[word] ?? 0` counts such a word as new.
Calling a built-in read from a record of functions throws a `TypeError` when its answer does not fit the record's function type, for example `valueOf` read from a `Record<string, (x: number) => number>`.
Other inherited names, such as `constructor`, read `undefined` from typed records.
@@ -0,0 +1,3 @@
- **Array subclasses:** A class that extends `Array` compiles: its instances are arrays, and `map`, `filter`, `slice` and the other methods that create arrays return instances of the subclass, as in Node.js.
A generic subclass (`class Bag<T> extends Array<T>`), a class that extends such a subclass, and a subclass that declares `Symbol.species` are unsupported.
A method whose result the subclass's constructor cannot construct throws a `TypeError`: the constructor's parameters must take the one length argument, and a `map` to another element type needs a constructor that adds no elements.
+84 -84
View File
@@ -21382,9 +21382,9 @@
"anchor": "err_invalid_mime_syntax",
"nodeStability": null,
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -23520,9 +23520,9 @@
"anchor": "err_throttled",
"nodeStability": null,
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -36684,9 +36684,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "supported",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -36707,9 +36707,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -36730,9 +36730,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -36776,9 +36776,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "supported",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -71946,9 +71946,9 @@
"inherited": false
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -71969,9 +71969,9 @@
"inherited": false
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -71992,9 +71992,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72015,9 +72015,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72038,9 +72038,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72061,9 +72061,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72176,9 +72176,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72199,9 +72199,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72222,9 +72222,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72245,9 +72245,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72268,9 +72268,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72291,9 +72291,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72314,9 +72314,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72337,9 +72337,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72360,9 +72360,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -72636,9 +72636,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -72751,9 +72751,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -72774,9 +72774,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -72797,9 +72797,9 @@
"inherited": false
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -73027,9 +73027,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -73050,9 +73050,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the documented scriptc module-loader subset.",
"verification": "test-backed"
}
},
{
@@ -73395,9 +73395,9 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"detail": "No static compiler lowering is registered for this API yet.",
"verification": "registry-gap"
"status": "partial",
"detail": "Implemented for the call shapes accepted by the compiler lowering.",
"verification": "test-backed"
}
},
{
@@ -25806,8 +25806,12 @@
"anchor": "dep0044-utilisarray",
"nodeStability": null,
"static": {
"status": "not-applicable",
"evidence": "compiler-chapter-policy:deprecations"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.isArray",
"tests": [
"tests/corpus/7700-util-deprecated-helpers.cjs",
"tests/corpus/7701-util-deprecated-helpers.ts"
]
},
"anchorSource": "exact"
},
@@ -26094,8 +26098,12 @@
"anchor": "dep0060-util_extend",
"nodeStability": null,
"static": {
"status": "not-applicable",
"evidence": "compiler-chapter-policy:deprecations"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util._extend",
"tests": [
"tests/corpus/7700-util-deprecated-helpers.cjs",
"tests/corpus/7701-util-deprecated-helpers.ts"
]
},
"anchorSource": "exact"
},
@@ -32763,6 +32771,8 @@
"tests/corpus/6702-ecdh-errors.js",
"tests/corpus/6708-dh-errors.js",
"tests/corpus/7440-tls-server-add-context.ts",
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7711-util-throttle.cjs",
"tests/corpus/7714-zlib-brotli-compress.cjs",
"tests/corpus/caught-system-error-fields.ts",
"tests/corpus/error-stack-frames.ts",
@@ -36688,8 +36698,11 @@
"anchor": "err_invalid_mime_syntax",
"nodeStability": null,
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:errors"
"status": "partial",
"evidence": "compiler-feature:errors.ERR_INVALID_MIME_SYNTAX",
"tests": [
"tests/corpus/7707-util-mime-type.cjs"
]
},
"anchorSource": "exact"
},
@@ -38826,8 +38839,11 @@
"anchor": "err_throttled",
"nodeStability": null,
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:errors"
"status": "partial",
"evidence": "compiler-feature:errors.ERR_THROTTLED",
"tests": [
"tests/corpus/7711-util-throttle.cjs"
]
},
"anchorSource": "exact"
},
@@ -52415,6 +52431,7 @@
"tests/corpus/6331-jose-root-entry/main.ts",
"tests/corpus/7743-transform-stream-identity.ts",
"tests/corpus/7747-text-codec-untyped-slot.js",
"tests/corpus/8162-navigator-global.cjs",
"tests/corpus/text-codec-values/main.ts",
"tests/corpus/webassembly-api.mjs",
"tests/corpus/webassembly-dylink/main.mjs",
@@ -54467,6 +54484,7 @@
"status": "partial",
"evidence": "compiler-feature:globals.navigator",
"tests": [
"tests/corpus/8162-navigator-global.cjs",
"tests/fixtures/node-types/navigator.ts",
"tests/harness/project-config.test.ts",
"tests/corpus/6331-jose-root-entry/main.ts"
@@ -54492,8 +54510,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:globals"
"status": "supported",
"evidence": "compiler-feature:globals.hardwareConcurrency",
"tests": [
"tests/corpus/8162-navigator-global.cjs",
"tests/fixtures/node-types/navigator.ts"
]
},
"anchorSource": "ancestor"
},
@@ -54515,8 +54537,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:globals"
"status": "partial",
"evidence": "compiler-feature:globals.language",
"tests": [
"tests/corpus/8162-navigator-global.cjs",
"tests/fixtures/node-types/navigator.ts"
]
},
"anchorSource": "ancestor"
},
@@ -54538,8 +54564,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:globals"
"status": "partial",
"evidence": "compiler-feature:globals.languages",
"tests": [
"tests/corpus/8162-navigator-global.cjs",
"tests/fixtures/node-types/navigator.ts"
]
},
"anchorSource": "ancestor"
},
@@ -54584,8 +54614,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:globals"
"status": "supported",
"evidence": "compiler-feature:globals.platform",
"tests": [
"tests/corpus/8162-navigator-global.cjs",
"tests/fixtures/node-types/navigator.ts"
]
},
"anchorSource": "ancestor"
},
@@ -101568,6 +101602,25 @@
"tests/corpus/5835-util-format-integer-specifiers.ts",
"tests/corpus/5884-inspect-layout-options.ts",
"tests/corpus/6428-promisify-callback-functions.ts",
"tests/corpus/7520-util-format-runtime.ts",
"tests/corpus/7521-util-format-runtime.cjs",
"tests/corpus/7522-promisify-untyped.cjs",
"tests/corpus/7523-promisify-untyped.ts",
"tests/corpus/7524-inspect-custom.ts",
"tests/corpus/7525-inspect-custom.cjs",
"tests/corpus/7526-inspect-options-runtime.ts",
"tests/corpus/7700-util-deprecated-helpers.cjs",
"tests/corpus/7701-util-deprecated-helpers.ts",
"tests/corpus/7702-util-signal-exit-code.cjs",
"tests/corpus/7703-util-aborted.cjs",
"tests/corpus/7704-util-aborted.ts",
"tests/corpus/7705-util-diff.cjs",
"tests/corpus/7706-util-diff.ts",
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts",
"tests/corpus/7710-util-debounce.cjs",
"tests/corpus/7711-util-throttle.cjs",
"tests/corpus/7712-util-debounce-throttle.ts",
"tests/corpus/7747-text-codec-untyped-slot.js",
"tests/corpus/node24-deep-equality-properties.js",
"tests/corpus/node24-deep-equality.cjs",
@@ -101654,8 +101707,12 @@
"inherited": false
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util._extend",
"tests": [
"tests/corpus/7700-util-deprecated-helpers.cjs",
"tests/corpus/7701-util-deprecated-helpers.ts"
]
},
"anchorSource": "exact"
},
@@ -101677,8 +101734,12 @@
"inherited": false
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.isArray",
"tests": [
"tests/corpus/7700-util-deprecated-helpers.cjs",
"tests/corpus/7701-util-deprecated-helpers.ts"
]
},
"anchorSource": "exact"
},
@@ -101700,8 +101761,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.util.MIMEType",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101723,8 +101788,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mime.toString",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101746,8 +101815,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mime.toJSON",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101769,8 +101842,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.MIMEType.parse",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101884,8 +101961,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.util.MIMEParams",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101907,8 +101988,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.delete",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101930,8 +102015,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.entries",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101953,8 +102042,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.get",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101976,8 +102069,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.has",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -101999,8 +102096,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.keys",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -102022,8 +102123,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.set",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -102045,8 +102150,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams.values",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -102068,8 +102177,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.mimeParams",
"tests": [
"tests/corpus/7707-util-mime-type.cjs",
"tests/corpus/7708-util-mime-type.ts"
]
},
"anchorSource": "exact"
},
@@ -102468,8 +102581,11 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.convertProcessSignalToExitCode",
"tests": [
"tests/corpus/7702-util-signal-exit-code.cjs"
]
},
"anchorSource": "exact"
},
@@ -102603,8 +102719,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.debounce",
"tests": [
"tests/corpus/7710-util-debounce.cjs",
"tests/corpus/7712-util-debounce-throttle.ts"
]
},
"anchorSource": "exact"
},
@@ -102626,8 +102746,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.throttle",
"tests": [
"tests/corpus/7711-util-throttle.cjs",
"tests/corpus/7712-util-debounce-throttle.ts"
]
},
"anchorSource": "exact"
},
@@ -102649,8 +102773,12 @@
"inherited": false
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.diff",
"tests": [
"tests/corpus/7705-util-diff.cjs",
"tests/corpus/7706-util-diff.ts"
]
},
"anchorSource": "exact"
},
@@ -102677,7 +102805,9 @@
"tests": [
"tests/corpus/1636-util-format.ts",
"tests/corpus/2440-console-inspect-args.ts",
"tests/corpus/5835-util-format-integer-specifiers.ts"
"tests/corpus/5835-util-format-integer-specifiers.ts",
"tests/corpus/7520-util-format-runtime.ts",
"tests/corpus/7521-util-format-runtime.cjs"
]
},
"anchorSource": "exact"
@@ -102705,7 +102835,9 @@
"tests": [
"tests/corpus/1636-util-format.ts",
"tests/corpus/2440-console-inspect-args.ts",
"tests/corpus/5835-util-format-integer-specifiers.ts"
"tests/corpus/5835-util-format-integer-specifiers.ts",
"tests/corpus/7520-util-format-runtime.ts",
"tests/corpus/7521-util-format-runtime.cjs"
]
},
"anchorSource": "exact"
@@ -102896,7 +103028,8 @@
"tests/corpus/1632-inspect-records.ts",
"tests/corpus/1637-inspect-dyn.ts",
"tests/corpus/2485-inspect-circular-refs.ts",
"tests/corpus/5884-inspect-layout-options.ts"
"tests/corpus/5884-inspect-layout-options.ts",
"tests/corpus/7526-inspect-options-runtime.ts"
]
},
"anchorSource": "exact"
@@ -102919,8 +103052,11 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.util.inspect",
"tests": [
"tests/corpus/7526-inspect-options-runtime.ts"
]
},
"anchorSource": "exact"
},
@@ -102942,8 +103078,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "compiler-feature:util.custom",
"tests": [
"tests/corpus/7524-inspect-custom.ts",
"tests/corpus/7525-inspect-custom.cjs"
]
},
"anchorSource": "ancestor"
},
@@ -103260,6 +103400,8 @@
"tests/fixtures/node-types/promisify-dns.ts",
"tests/corpus/6428-promisify-callback-functions.ts",
"tests/fixtures/node-types/promisify-callback-functions.ts",
"tests/corpus/7522-promisify-untyped.cjs",
"tests/corpus/7523-promisify-untyped.ts",
"tests/harness/project-config.test.ts"
]
},
@@ -103475,8 +103617,12 @@
"inherited": true
},
"static": {
"status": "not-implemented",
"evidence": "compiler-unmatched:util"
"status": "partial",
"evidence": "surface-manifest:node-builtin.util.aborted",
"tests": [
"tests/corpus/7703-util-aborted.cjs",
"tests/corpus/7704-util-aborted.ts"
]
},
"anchorSource": "exact"
},
+19 -4
View File
@@ -187,6 +187,13 @@
"node-builtin.util.callbackify": ["tests/corpus/5190-util-callbackify.cjs", "tests/corpus/5191-util-callbackify.ts", "tests/fixtures/node-types/util-callables.ts"],
"node-builtin.util.debuglog": ["tests/corpus/5192-util-debuglog.cjs", "tests/corpus/5193-util-debuglog.ts", "tests/fixtures/node-types/util-callables.ts"],
"node-builtin.util.debug": ["tests/corpus/5192-util-debuglog.cjs", "tests/corpus/5193-util-debuglog.ts"],
"node-builtin.util.isArray": ["tests/corpus/7700-util-deprecated-helpers.cjs", "tests/corpus/7701-util-deprecated-helpers.ts"],
"node-builtin.util._extend": ["tests/corpus/7700-util-deprecated-helpers.cjs", "tests/corpus/7701-util-deprecated-helpers.ts"],
"node-builtin.util.convertProcessSignalToExitCode": ["tests/corpus/7702-util-signal-exit-code.cjs"],
"node-builtin.util.aborted": ["tests/corpus/7703-util-aborted.cjs", "tests/corpus/7704-util-aborted.ts"],
"node-builtin.util.diff": ["tests/corpus/7705-util-diff.cjs", "tests/corpus/7706-util-diff.ts"],
"node-builtin.util.debounce": ["tests/corpus/7710-util-debounce.cjs", "tests/corpus/7712-util-debounce-throttle.ts"],
"node-builtin.util.throttle": ["tests/corpus/7711-util-throttle.cjs", "tests/corpus/7712-util-debounce-throttle.ts"],
"node-builtin.util": ["tests/corpus/2440-console-inspect-args.ts", "tests/corpus/2912-promisify-fs-readfile.ts"],
"node-builtin.worker_threads": ["tests/corpus/957-builtins-namespace.ts", "tests/corpus/native-worker-messages.ts", "tests/corpus/native-worker-references.ts"],
"node-builtin.zlib": ["tests/corpus/1404-zlib-crypto-bytes.ts", "tests/corpus/2921-zlib-callbacks.ts", "tests/corpus/3115-zlib-static-compression-levels.ts", "tests/corpus/5370-zlib-stream-roundtrip.ts", "tests/corpus/5371-zlib-stream-chunking.cjs", "tests/corpus/5373-zlib-stream-options.cjs", "tests/corpus/5378-zlib-sync-options.cjs", "tests/corpus/5379-zlib-callback-options.ts", "tests/corpus/5415-zlib-dynamic-inputs.cjs"],
@@ -215,8 +222,10 @@
{ "chapter": "webcrypto", "signatures": ["Class: `CryptoKey`", "`cryptoKey.algorithm`", "`extractable` Type: {boolean}", "`type` Type: {string} One of `'secret'`, `'private'`, or `'public'`.", "`usages` Type: {string\\[]}"], "status": "partial", "evidence": ["tests/corpus/7124-webcrypto-secret-keys.ts", "tests/corpus/6291-webcrypto-hmac-sign-verify.ts", "tests/corpus/6294-webcrypto-js-values.mjs", "tests/corpus/6295-jose-hs256/main.mjs"] },
{ "chapter": "webcrypto", "signatures": ["Class: `Crypto`"], "status": "partial", "evidence": ["tests/corpus/7120-webcrypto-random-uuid.ts", "tests/corpus/7121-webcrypto-crypto-object.mjs", "tests/corpus/6293-webcrypto-digest.ts"] },
{ "chapter": "webcrypto", "symbols": ["crypto.randomUUID", "crypto.getRandomValues"], "status": "supported", "evidence": ["tests/corpus/7120-webcrypto-random-uuid.ts", "tests/corpus/7121-webcrypto-crypto-object.mjs", "tests/corpus/6204-crypto-get-random-values.ts", "tests/corpus/6205-crypto-get-random-values.js"] },
{ "chapter": "globals", "signatures": ["`navigator`"], "status": "partial", "evidence": ["tests/fixtures/node-types/navigator.ts", "tests/harness/project-config.test.ts", "tests/corpus/6331-jose-root-entry/main.ts"] },
{ "chapter": "globals", "signatures": ["`navigator`"], "status": "partial", "evidence": ["tests/corpus/8162-navigator-global.cjs", "tests/fixtures/node-types/navigator.ts", "tests/harness/project-config.test.ts", "tests/corpus/6331-jose-root-entry/main.ts"] },
{ "chapter": "globals", "signatures": ["`userAgent` Type: {string}"], "status": "supported", "evidence": ["tests/fixtures/node-types/navigator.ts", "tests/harness/project-config.test.ts"] },
{ "chapter": "globals", "signatures": ["`hardwareConcurrency` Type: {number}", "`platform` Type: {string}"], "status": "supported", "evidence": ["tests/corpus/8162-navigator-global.cjs", "tests/fixtures/node-types/navigator.ts"] },
{ "chapter": "globals", "signatures": ["`language` Type: {string}", "`languages` Type: {string\\[]}"], "status": "partial", "evidence": ["tests/corpus/8162-navigator-global.cjs", "tests/fixtures/node-types/navigator.ts"] },
{ "chapter": "globals", "signatures": ["Class: `CryptoKey`", "Class: `SubtleCrypto`"], "status": "partial", "evidence": ["tests/corpus/6291-webcrypto-hmac-sign-verify.ts", "tests/corpus/6292-webcrypto-hmac-errors.ts", "tests/corpus/6293-webcrypto-digest.ts", "tests/corpus/6294-webcrypto-js-values.mjs", "tests/corpus/6295-jose-hs256/main.mjs"] },
{ "chapter": "errors", "parent": "Class: `SystemError`", "symbols": ["code", "errno", "syscall", "path", "dest"], "status": "partial", "evidence": ["tests/corpus/caught-system-error-fields.ts", "tests/fixtures/node-types/terminal-error-fields.ts", "tests/harness/project-config.test.ts"] },
{"chapter": "events", "symbols": ["EventTarget", "eventTarget.addEventListener", "eventTarget.removeEventListener", "eventTarget.dispatchEvent"], "status": "partial", "evidence": ["tests/corpus/5130-event-target-dispatch.js", "tests/corpus/5131-event-target-listener-errors.js", "tests/corpus/5132-event-target-typed.ts", "tests/corpus/5133-abort-signal-event-target.ts", "tests/corpus/5135-event-target-warnings.js", "tests/corpus/5240-event-target-subclass.ts", "tests/corpus/5242-event-target-subclass-hierarchy.ts", "tests/corpus/5243-event-target-subclass-dynamic.ts", "tests/corpus/5244-event-target-subclass.js", "tests/corpus/5245-event-target-subclass-signals.ts", "tests/corpus/5248-event-target-subclass-warnings.ts"]},
@@ -253,9 +262,11 @@
{"chapter": "worker_threads", "symbols": ["resourceLimits"], "status": "partial", "evidence": ["tests/corpus/5806-worker-resource-limits.ts"]},
{"chapter": "worker_threads", "symbols": ["BroadcastChannel extends EventTarget", "broadcastChannel.close", "broadcastChannel.postMessage", "broadcastChannel.ref", "broadcastChannel.unref", "onmessage"], "status": "partial", "evidence": ["tests/corpus/5800-broadcast-channel.ts", "tests/corpus/5801-broadcast-channel.cjs", "tests/corpus/5802-broadcast-channel-workers.ts"]},
{"chapter": "util", "symbols": ["util.types.isAnyArrayBuffer", "util.types.isArrayBuffer", "util.types.isArrayBufferView", "util.types.isDataView", "util.types.isTypedArray", "util.types.isUint8Array", "util.types.isUint8ClampedArray", "util.types.isUint16Array", "util.types.isUint32Array", "util.types.isInt8Array", "util.types.isInt16Array", "util.types.isInt32Array", "util.types.isFloat32Array", "util.types.isFloat64Array", "util.types.isMap", "util.types.isSet", "util.types.isWeakMap", "util.types.isWeakSet", "util.types.isRegExp", "util.types.isNativeError", "util.types.isPromise", "util.types.isProxy", "util.types.isAsyncFunction", "util.types.isGeneratorFunction", "util.types.isGeneratorObject"], "status": "partial", "evidence": ["tests/corpus/node24-util-types.ts", "tests/corpus/node24-util-types.js", "tests/corpus/node24-util-types.cjs", "tests/fixtures/node-types/util-types.ts"]},
{"chapter": "util", "symbols": ["util.format", "util.formatWithOptions"], "status": "partial", "evidence": ["tests/corpus/1636-util-format.ts", "tests/corpus/2440-console-inspect-args.ts", "tests/corpus/5835-util-format-integer-specifiers.ts"]},
{"chapter": "util", "symbols": ["util.format", "util.formatWithOptions"], "status": "partial", "evidence": ["tests/corpus/1636-util-format.ts", "tests/corpus/2440-console-inspect-args.ts", "tests/corpus/5835-util-format-integer-specifiers.ts", "tests/corpus/7520-util-format-runtime.ts", "tests/corpus/7521-util-format-runtime.cjs"]},
{"chapter": "util", "symbols": ["util.types.isAnyArrayBuffer", "util.types.isArrayBuffer", "util.types.isArrayBufferView", "util.types.isDataView", "util.types.isTypedArray", "util.types.isUint8Array", "util.types.isUint8ClampedArray", "util.types.isUint16Array", "util.types.isUint32Array", "util.types.isInt8Array", "util.types.isInt16Array", "util.types.isInt32Array", "util.types.isFloat32Array", "util.types.isFloat64Array", "util.types.isMap", "util.types.isSet", "util.types.isWeakMap", "util.types.isWeakSet", "util.types.isRegExp", "util.types.isNativeError", "util.types.isPromise", "util.types.isProxy", "util.types.isAsyncFunction", "util.types.isGeneratorFunction", "util.types.isGeneratorObject", "util.types.isDate", "util.types.isSharedArrayBuffer", "util.types.isMapIterator", "util.types.isSetIterator", "util.types.isKeyObject", "util.types.isNumberObject", "util.types.isStringObject", "util.types.isBooleanObject", "util.types.isBigIntObject", "util.types.isSymbolObject", "util.types.isBoxedPrimitive", "util.types.isBigInt64Array", "util.types.isBigUint64Array", "util.types.isFloat16Array", "util.types.isCryptoKey", "util.types.isExternal"], "status": "partial", "evidence": ["tests/corpus/5831-util-types-brands.ts", "tests/corpus/5832-util-types-brands-dynamic.js", "tests/corpus/node24-util-types.ts", "tests/corpus/node24-util-types.js", "tests/corpus/node24-util-types.cjs", "tests/fixtures/node-types/util-types.ts"]},
{ "chapter": "util", "signatures": ["`util.inspect(object[, options])`"], "status": "partial", "evidence": ["tests/corpus/1630-inspect-scalars.ts", "tests/corpus/1632-inspect-records.ts", "tests/corpus/1637-inspect-dyn.ts", "tests/corpus/2485-inspect-circular-refs.ts", "tests/corpus/5884-inspect-layout-options.ts"] },
{ "chapter": "util", "signatures": ["`util.inspect(object[, options])`"], "status": "partial", "evidence": ["tests/corpus/1630-inspect-scalars.ts", "tests/corpus/1632-inspect-records.ts", "tests/corpus/1637-inspect-dyn.ts", "tests/corpus/2485-inspect-circular-refs.ts", "tests/corpus/5884-inspect-layout-options.ts", "tests/corpus/7526-inspect-options-runtime.ts"] },
{ "chapter": "util", "signatures": ["`util.inspect(object[, showHidden[, depth[, colors]]])`"], "status": "partial", "evidence": ["tests/corpus/7526-inspect-options-runtime.ts"] },
{ "chapter": "util", "signatures": ["`custom` Type: {symbol} that can be used to declare custom inspect functions."], "status": "partial", "evidence": ["tests/corpus/7524-inspect-custom.ts", "tests/corpus/7525-inspect-custom.cjs"] },
{ "chapter": "util", "symbols": ["util.styleText"], "status": "partial", "evidence": ["tests/corpus/node24-style-text.ts", "tests/corpus/node24-style-text-validation.js", "tests/corpus/node24-style-text-environment.js", "tests/corpus/node24-style-text.cjs", "tests/fixtures/node-types/style-text.ts"] },
{ "chapter": "util", "symbols": ["util.isDeepStrictEqual"], "status": "partial", "evidence": ["tests/corpus/node24-deep-equality.ts", "tests/corpus/node24-deep-equality.cjs", "tests/corpus/node24-deep-equality-properties.js", "tests/fixtures/node-types/deep-equality.ts", "packages/compiler/test/deep-equality.test.ts"] },
{ "chapter": "deprecations", "symbols": ["util.toUSVString"], "status": "not-applicable" },
@@ -265,6 +276,10 @@
{ "chapter": "buffer", "symbols": ["buffer.isAscii", "buffer.isUtf8", "buffer.transcode"], "status": "partial", "evidence": ["tests/corpus/node24-buffer-encoding.ts", "tests/corpus/node24-buffer-encoding-errors.ts", "tests/fixtures/node-types/text-encoding.ts"] },
{ "chapter": "util", "parent": "Class: `util.TextEncoder`", "signatures": ["`textEncoder.encodeInto(src, dest)`", "`encoding` Type: {string}"], "status": "partial", "evidence": ["tests/corpus/node24-text-encode-into.ts", "tests/corpus/node24-text-codec-properties.ts", "tests/fixtures/node-types/text-encoding.ts"] },
{ "chapter": "util", "parent": "Class: `util.TextDecoder`", "signatures": ["`encoding` Type: {string}", "`fatal` Type: {boolean}", "`ignoreBOM` Type: {boolean}"], "status": "partial", "evidence": ["tests/corpus/node24-text-codec-properties.ts", "tests/fixtures/node-types/text-encoding.ts"] },
{ "chapter": "util", "symbols": ["util.MIMEType", "util.MIMEParams", "MIMEType.parse", "mime.toString", "mime.toJSON", "mimeParams.delete", "mimeParams.entries", "mimeParams.get", "mimeParams.has", "mimeParams.keys", "mimeParams.set", "mimeParams.values"], "status": "partial", "evidence": ["tests/corpus/7707-util-mime-type.cjs", "tests/corpus/7708-util-mime-type.ts"] },
{ "chapter": "util", "signatures": ["`mimeParams[Symbol.iterator]()`"], "status": "partial", "evidence": ["tests/corpus/7707-util-mime-type.cjs", "tests/corpus/7708-util-mime-type.ts"] },
{ "chapter": "errors", "symbols": ["ERR_INVALID_MIME_SYNTAX"], "status": "partial", "evidence": ["tests/corpus/7707-util-mime-type.cjs"] },
{ "chapter": "errors", "symbols": ["ERR_THROTTLED"], "status": "partial", "evidence": ["tests/corpus/7711-util-throttle.cjs"] },
{ "chapter": "util", "symbols": ["util.parseEnv"], "status": "partial", "evidence": ["tests/corpus/node24-env-parse.ts", "tests/corpus/node24-env-parse-errors.ts", "tests/corpus/node24-env-imports.cjs", "tests/fixtures/node-types/env-files.ts", "tests/harness/project-config.test.ts"] },
{ "chapter": "process", "symbols": ["process.memoryUsage.rss"], "status": "partial", "evidence": ["tests/corpus/5210-process-memory-usage.ts"] },
{ "chapter": "perf_hooks", "symbols": ["performance.now"], "status": "partial", "evidence": ["tests/corpus/2427-perf-hooks-now.ts", "tests/corpus/2446-performance-global.ts"] },
@@ -409,7 +424,7 @@
{ "chapter": "test", "parent": "Class: `TestContext`", "symbols": ["context.before", "context.after", "context.beforeEach", "context.afterEach", "context.plan", "context.fullName"], "status": "partial", "evidence": ["tests/fixtures/node-test/cases/ctx-hooks.ts", "tests/fixtures/node-test/cases/ctx-plan.ts", "tests/harness/node-test.test.ts"] },
{ "chapter": "test", "symbols": ["getTestContext"], "status": "partial", "evidence": ["tests/fixtures/node-test/cases/get-test-context.ts", "tests/fixtures/node-test/cases/get-test-context-cancelled.ts", "tests/harness/node-test.test.ts"] },
{ "chapter": "test", "symbols": ["describe.skip", "describe.todo", "describe.only", "suite.skip", "suite.todo", "suite.only", "it.skip", "it.todo", "it.only"], "status": "partial", "evidence": ["tests/fixtures/node-test/cases/suite-variants.ts", "tests/fixtures/node-test/cases/only-nested.ts", "tests/fixtures/node-test/cases/todo-suites.ts", "tests/harness/node-test.test.ts"] },
{ "chapter": "util", "signatures": ["`util.promisify(original)`"], "status": "partial", "evidence": ["tests/corpus/1473-promisify-execfile.ts", "tests/corpus/1573-promisify-execfile-env-spread.ts", "tests/corpus/2912-promisify-fs-readfile.ts", "tests/corpus/5625-promisify-exec.ts", "tests/corpus/5626-promisify-forms.ts", "tests/fixtures/node-types/promisify-fs.ts", "tests/corpus/5628-promisify-timers.ts", "tests/fixtures/node-types/promisify-timers.ts", "tests/corpus/5629-promisify-stream.ts", "tests/corpus/5630-promisify-zlib.ts", "tests/fixtures/node-types/promisify-zlib.ts", "tests/corpus/5631-promisify-crypto.ts", "tests/fixtures/node-types/promisify-crypto.ts", "tests/corpus/5632-promisify-dns.ts", "tests/fixtures/node-types/promisify-dns.ts", "tests/corpus/6428-promisify-callback-functions.ts", "tests/fixtures/node-types/promisify-callback-functions.ts", "tests/harness/project-config.test.ts"] },
{ "chapter": "util", "signatures": ["`util.promisify(original)`"], "status": "partial", "evidence": ["tests/corpus/1473-promisify-execfile.ts", "tests/corpus/1573-promisify-execfile-env-spread.ts", "tests/corpus/2912-promisify-fs-readfile.ts", "tests/corpus/5625-promisify-exec.ts", "tests/corpus/5626-promisify-forms.ts", "tests/fixtures/node-types/promisify-fs.ts", "tests/corpus/5628-promisify-timers.ts", "tests/fixtures/node-types/promisify-timers.ts", "tests/corpus/5629-promisify-stream.ts", "tests/corpus/5630-promisify-zlib.ts", "tests/fixtures/node-types/promisify-zlib.ts", "tests/corpus/5631-promisify-crypto.ts", "tests/fixtures/node-types/promisify-crypto.ts", "tests/corpus/5632-promisify-dns.ts", "tests/fixtures/node-types/promisify-dns.ts", "tests/corpus/6428-promisify-callback-functions.ts", "tests/fixtures/node-types/promisify-callback-functions.ts", "tests/corpus/7522-promisify-untyped.cjs", "tests/corpus/7523-promisify-untyped.ts", "tests/harness/project-config.test.ts"] },
{ "chapter": "typescript", "symbols": ["type"], "status": "supported", "evidence": ["tests/corpus/2702-type-import-link-static/main.ts", "tests/corpus/2703-type-import-link-static-reexport/main.ts", "tests/corpus/2704-type-import-link-static-success/main.ts", "tests/corpus/2707-type-import-link-static-default-reexport/main.ts", "tests/harness/errors.test.ts"] },
{ "chapter": "zlib", "signatures": ["Class: `zlib.Deflate`", "Class: `zlib.Inflate`", "Class: `zlib.Gzip`", "Class: `zlib.Gunzip`", "Class: `zlib.DeflateRaw`", "Class: `zlib.InflateRaw`", "Class: `zlib.Unzip`", "Class: `zlib.ZlibBase`", "`zlib.close([callback])`", "`zlib.flush([kind, ]callback)`", "`zlib.params(level, strategy, callback)`", "`zlib.reset()`", "`bytesWritten` Type: {number}", "Class: `Options`"], "status": "partial", "evidence": ["tests/corpus/5370-zlib-stream-roundtrip.ts", "tests/corpus/5371-zlib-stream-chunking.cjs", "tests/corpus/5372-zlib-stream-errors.cjs", "tests/corpus/5373-zlib-stream-options.cjs", "tests/corpus/5374-zlib-stream-flush-params.ts", "tests/corpus/5375-zlib-stream-promises.ts", "tests/corpus/5377-zlib-stream-backpressure.cjs"] },
{ "chapter": "zlib", "signatures": ["Class: `zlib.BrotliCompress`", "Class: `BrotliOptions`"], "status": "partial", "evidence": ["tests/corpus/7714-zlib-brotli-compress.cjs"] },
+33
View File
@@ -17,6 +17,14 @@ set(SCRIPTC_HELPER_ARCH "arm64" CACHE STRING
# Linux packages ship this process-isolated helper as a fully static host
# executable so it runs independently of the destination libc and libstdc++.
option(SCRIPTC_STATIC_LINUX_BUILD "Build a static Linux helper executable" OFF)
# The release Linux helpers link an LLVM built with ThinLTO and a profile of
# the helper's code generation (llvm-dist.mjs). Its archives hold bitcode, so
# the helper compiles and links with ThinLTO too, which needs clang and lld.
option(SCRIPTC_LLVM_THINLTO "Compile and link the helper with ThinLTO" OFF)
set(SCRIPTC_LLVM_PROFILE_USE "" CACHE FILEPATH
"Indexed profile the helper's own sources are optimized with")
option(SCRIPTC_LLVM_PROFILE_GENERATE
"Instrument the helper's sources to collect that profile" OFF)
# These must be cache variables before project() enables the Apple toolchain.
# A target property named OSX_DEPLOYMENT_TARGET is not recognized by CMake and
@@ -219,6 +227,31 @@ else()
endif()
target_link_libraries(scriptc-llvm-codegen PRIVATE ${SCRIPTC_LLVM_LIBS} ${SCRIPTC_LLVM_SYSTEM_LIBS})
if(SCRIPTC_LLVM_THINLTO)
target_compile_options(scriptc-llvm-codegen PRIVATE -flto=thin)
# The thin link optimizes and compiles all of LLVM's code the helper
# reaches; the cache makes a relink after a helper edit incremental.
target_link_options(scriptc-llvm-codegen PRIVATE
-flto=thin
-fuse-ld=lld
"LINKER:--thinlto-jobs=all"
"LINKER:--thinlto-cache-dir=${CMAKE_BINARY_DIR}/thinlto-cache"
)
endif()
if(SCRIPTC_LLVM_PROFILE_USE)
# The profile covers LLVM's sources and the helper's. Functions it does
# not cover, or whose control flow changed since, are optimized without it.
target_compile_options(scriptc-llvm-codegen PRIVATE
"-fprofile-use=${SCRIPTC_LLVM_PROFILE_USE}"
-Wno-profile-instr-unprofiled
-Wno-profile-instr-out-of-date
)
endif()
if(SCRIPTC_LLVM_PROFILE_GENERATE)
target_compile_options(scriptc-llvm-codegen PRIVATE -fprofile-generate)
target_link_options(scriptc-llvm-codegen PRIVATE -fprofile-generate)
endif()
if(APPLE)
# Homebrew's static LLVM archives contain broad component object files.
# Export only the process entry point so archive-global LLVM symbols do not
+19 -2
View File
@@ -33,11 +33,11 @@ lowering, verifies before and after optimization, and publishes through a
private sibling file so a failed or interrupted request cannot truncate the
requested output.
Repeating `--output` divides the program into that many partitions, which are compiled concurrently and linked together. The helper splits the emitter's LLVM assembly text directly, so partitions also parse concurrently; input outside the emitter's narrow grammar is parsed whole and split with LLVM instead. Internal definitions become hidden so partitions can reference each other. At opt-level 0 each partition is compiled independently. Optimized partitions follow the ThinLTO model: each is simplified and summarized on its own thread, a thin link decides which small functions every partition imports for inlining and which hidden definitions become internal again, and each partition is then optimized and compiled on its own thread. Partition placement depends only on the module and the partition count, so output never depends on the host.
Repeating `--output` divides the program into that many partitions, which are compiled concurrently and linked together. The helper splits the emitter's LLVM assembly text directly, so partitions also parse concurrently; input outside the emitter's narrow grammar is parsed whole and split with LLVM instead. Internal definitions that no other definition reaches are left out of every partition, and the others become hidden so partitions can reference each other. At opt-level 0 each partition is compiled independently. Optimized partitions follow the ThinLTO model: each is simplified and summarized on its own thread, a thin link decides which small functions every partition imports for inlining and which hidden definitions become internal again, and each partition is then optimized and compiled on its own thread. Partition placement depends only on the module and the partition count, so output never depends on the host.
WebAssembly code generation differs from LLVM's default pipeline in two ways that do not change its output. The pass that gives multiple-entry loops a single entry runs only on functions whose control flow is irreducible; its reachability analysis grows with the square of a function's block count even when it has nothing to change. Object emission also leaves out the module pass that collects external symbols for assembly declarations, so each function's machine code is freed once it is printed instead of when the whole module is compiled.
`--cache-dir <dir>` names a private directory the caller owns for one helper build. Simplified partitions are stored under the hash of their exact source and objects under the hash of the exact module after importing, each with a trailing digest and published by rename, so a rebuild recompiles only the partitions an edit can affect.
`--cache-dir <dir>` names a private directory the caller owns for one helper build. Simplified partitions are stored under the hash of their exact source and objects under the hash of the exact module after importing, each with a trailing digest and published by rename, so a rebuild recompiles only the partitions an edit can affect. Partitions drop the names of their struct types before the thin link, which would otherwise number same-named types from different partitions in an order that any edit can shift, changing the module after importing in partitions the edit did not touch.
`--import-bitcode <unit.bc>`, given once per runtime-pack unit that ships bitcode, imports runtime functions for inlining; scriptc's program builds do not pass it. Small runtime functions reachable from the program's runtime calls are imported as `available_externally` so LLVM can inline them; the runtime objects remain the only definitions. The helper never runs a sanitizer pass, so with import it also drops the emitter's inert `sanitize_address` attributes, which would otherwise block that inlining. Without `--import-bitcode` the module is optimized exactly as emitted.
@@ -58,3 +58,20 @@ scriptc-llvm-codegen prune-import --input unit.opt.bc --output unit.bc
```
Both commands keep only what a program build can import: the importable bodies within the size limit at their call distance from any public function, and the constants they copy. Every other definition becomes a declaration, so a program imports exactly what it would from the whole unit while reading a fraction of it. Unpromoted unit-local symbols stay local, so release bitcode offers only bodies that need none of them.
## Linux release builds
The Linux helper packages are released linked against LLVM 22.1.8 built from its release sources with ThinLTO and with `llvm.profdata.gz`, a profile of the helper's own code generation (`llvm-dist.mjs`). The helper's code generation is 5-9% faster with it than when the helper links LLVM's release archive, and its objects are identical. The release workflow downloads that build from the `LLVM_DIST_TAG` release of this repository; when the archive is missing, the helper links LLVM's release archive instead.
To build and use it locally, with clang, lld and llvm-profdata 22.1.8 on `PATH` (LLVM's release archive for the host has them):
```console
$ node scripts/build-llvm-dist.mjs --source llvm-project-22.1.8.src --prefix <dir>
$ LLVM_DIR=<dir>/lib/cmake/llvm SCRIPTC_LLVM_THINLTO=1 pnpm --filter @scriptc/llvm-linux-x64-gnu build:native
```
`SCRIPTC_LLVM_THINLTO=1` compiles and links the helper with clang, lld and ThinLTO, since that LLVM's archives hold bitcode, and optimizes the helper's own sources with the same profile. The link takes about 4 minutes on 4 cores.
The `llvm-dist` workflow (run by hand) builds the archive for x64 and arm64, checks that a helper linked against it gives the same objects as one linked against LLVM's release archive (`scripts/check-llvm-dist.mjs`), and attaches it to the release. The arm64 build uses the profile collected on x64, and its log reports how many functions the profile does not match there.
The profile depends on LLVM's sources and the kind of code scriptc emits, not on scriptc's commits. `scripts/refresh-llvm-profile.mjs` collects a new one after an LLVM version change: it builds LLVM with IR instrumentation and an instrumented helper, runs that helper on tsc-ts, five Effect fixtures, the runtime benchmark workloads and every 50th corpus program (`scripts/llvm-helper-inputs.mjs`), and merges the result. A new profile or LLVM version gets a new `LLVM_DIST_TAG`.
+79
View File
@@ -0,0 +1,79 @@
/* The static Linux helper build shared by the four Linux helper packages,
* scripts/refresh-llvm-profile.mjs and scripts/check-llvm-dist.mjs. */
import { execFileSync } from "node:child_process";
import {
chmodSync,
copyFileSync,
existsSync,
mkdirSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { helperLlvmDistArgs } from "./llvm-dist.mjs";
import { nativeTargetCmakeArgs } from "./targets.mjs";
const DATA_LAYOUTS = {
x64: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
arm64:
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
};
/** Configures and builds the helper for `arch` (`x64` or `arm64`) and `libc`
* (`gnu` or `musl`) in `build` against LLVM_DIR, and writes the stripped
* executable to `output`. musl builds take the compilers from CC and CXX. */
export function buildLinuxHelper({ arch, libc, version, build, output }) {
const triple = `${arch === "x64" ? "x86_64" : "aarch64"}-unknown-linux-${libc}`;
// CMake drops the other definitions when a reconfigure changes the
// compiler, so a build directory configured for another LLVM or build
// kind starts over.
const kind = JSON.stringify({
llvm: process.env.LLVM_DIR ?? null,
thinLTO: process.env.SCRIPTC_LLVM_THINLTO === "1",
profileGenerate: process.env.SCRIPTC_LLVM_PROFILE_GENERATE === "1",
cc: process.env.CC ?? null,
cxx: process.env.CXX ?? null,
});
const stamp = join(build, "scriptc-helper-build.json");
if (existsSync(build) && (!existsSync(stamp) || readFileSync(stamp, "utf8") !== kind))
rmSync(build, { recursive: true, force: true });
mkdirSync(build, { recursive: true });
writeFileSync(stamp, kind);
execFileSync(
"cmake",
[
"-S",
fileURLToPath(new URL(".", import.meta.url)),
"-B",
build,
"-G",
"Ninja",
...(libc === "musl"
? [
`-DCMAKE_C_COMPILER=${process.env.CC ?? "cc"}`,
`-DCMAKE_CXX_COMPILER=${process.env.CXX ?? "c++"}`,
]
: []),
`-DLLVM_DIR=${process.env.LLVM_DIR ?? "/usr/lib/llvm-22/lib/cmake/llvm"}`,
`-DSCRIPTC_PACKAGE_VERSION=${version}`,
`-DSCRIPTC_DEFAULT_TARGET=${triple}`,
`-DSCRIPTC_DEFAULT_DATA_LAYOUT=${DATA_LAYOUTS[arch]}`,
...nativeTargetCmakeArgs,
"-DSCRIPTC_STATIC_LINUX_BUILD=ON",
"-DCMAKE_EXE_LINKER_FLAGS=-static",
"-DCMAKE_BUILD_TYPE=Release",
// Later definitions win, so these can select clang for musl builds.
...helperLlvmDistArgs(build),
],
{ stdio: "inherit" },
);
execFileSync("cmake", ["--build", build, "--target", "scriptc-llvm-codegen"], {
stdio: "inherit",
});
mkdirSync(dirname(output), { recursive: true });
copyFileSync(join(build, "scriptc-llvm-codegen"), output);
execFileSync("strip", [output], { stdio: "inherit" });
chmodSync(output, 0o755);
}
+96
View File
@@ -0,0 +1,96 @@
/* The LLVM distribution the Linux helpers link in releases: LLVM built from
* the release sources with ThinLTO and with a profile of the helper's own
* code generation (llvm.profdata.gz). scripts/build-llvm-dist.mjs builds it,
* the llvm-dist workflow attaches it to the LLVM_DIST_TAG release of this
* repository, and scripts/refresh-llvm-profile.mjs collects the profile. */
import { execFileSync } from "node:child_process";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import { gunzipSync } from "node:zlib";
export const LLVM_VERSION = "22.1.8";
/** The release of this repository that holds the distribution archives. A
* new profile or LLVM version gets a new tag. */
export const LLVM_DIST_TAG = "llvm-22.1.8-pgo.1";
export const llvmProfile = fileURLToPath(new URL("./llvm.profdata.gz", import.meta.url));
/** The archive name for a Linux architecture (`x64` or `arm64`). */
export function llvmDistAsset(arch) {
return `scriptc-llvm-${LLVM_VERSION}-linux-${arch}.tar.xz`;
}
/** Writes the uncompressed profile into `dir` and returns its path. */
export function writeLlvmProfile(dir, profile = llvmProfile) {
mkdirSync(dir, { recursive: true });
const path = join(dir, "llvm.profdata");
writeFileSync(path, gunzipSync(readFileSync(profile)));
return path;
}
/** CMake arguments for an LLVM build with the helper's targets, static,
* without tools or tests. `profile` builds with that indexed profile and
* ThinLTO; `instrumented` builds the IR-instrumented libraries the profile
* is collected with. clang and lld come from PATH and must be LLVM_VERSION,
* since the profile's format and hashes follow the compiler. */
export function llvmCmakeArgs({ source, build, prefix, profile, instrumented }) {
const version = execFileSync("clang", ["--version"], { encoding: "utf8" });
if (!version.includes(`clang version ${LLVM_VERSION}`))
throw new Error(`the LLVM distribution is built with clang ${LLVM_VERSION}; found ${version}`);
return [
"-S",
join(source, "llvm"),
"-B",
build,
"-G",
"Ninja",
"-DCMAKE_BUILD_TYPE=Release",
`-DCMAKE_INSTALL_PREFIX=${prefix}`,
"-DCMAKE_C_COMPILER=clang",
"-DCMAKE_CXX_COMPILER=clang++",
"-DLLVM_USE_LINKER=lld",
"-DLLVM_TARGETS_TO_BUILD=X86;AArch64;WebAssembly",
"-DLLVM_ENABLE_PROJECTS=",
"-DLLVM_ENABLE_ASSERTIONS=OFF",
"-DLLVM_ENABLE_ZLIB=FORCE_ON",
"-DLLVM_ENABLE_ZSTD=FORCE_ON",
"-DLLVM_USE_STATIC_ZSTD=ON",
"-DLLVM_ENABLE_TERMINFO=OFF",
"-DLLVM_ENABLE_LIBXML2=OFF",
"-DLLVM_ENABLE_LIBEDIT=OFF",
"-DLLVM_ENABLE_LIBPFM=OFF",
"-DLLVM_INCLUDE_TESTS=OFF",
"-DLLVM_INCLUDE_EXAMPLES=OFF",
"-DLLVM_INCLUDE_BENCHMARKS=OFF",
"-DLLVM_INCLUDE_DOCS=OFF",
"-DLLVM_BUILD_TOOLS=OFF",
...(instrumented ? ["-DLLVM_BUILD_INSTRUMENTED=IR", "-DLLVM_BUILD_RUNTIME=OFF"] : []),
...(profile ? ["-DLLVM_ENABLE_LTO=Thin", `-DLLVM_PROFDATA_FILE=${profile}`] : []),
];
}
/** Extra CMake arguments for a Linux helper package build. With
* SCRIPTC_LLVM_THINLTO=1, LLVM_DIR names a distribution from
* scripts/build-llvm-dist.mjs: its archives hold ThinLTO bitcode, so the
* helper compiles and links with clang, lld and ThinLTO, and its own sources
* use the same profile. SCRIPTC_LLVM_PROFILE_GENERATE=1 instruments the
* helper's sources against an instrumented LLVM. */
export function helperLlvmDistArgs(build) {
const args = [];
if (process.env.SCRIPTC_LLVM_THINLTO === "1")
args.push(
"-DCMAKE_C_COMPILER=clang",
"-DCMAKE_CXX_COMPILER=clang++",
"-DSCRIPTC_LLVM_THINLTO=ON",
`-DSCRIPTC_LLVM_PROFILE_USE=${writeLlvmProfile(build)}`,
);
else args.push("-DSCRIPTC_LLVM_THINLTO=OFF", "-DSCRIPTC_LLVM_PROFILE_USE=");
if (process.env.SCRIPTC_LLVM_PROFILE_GENERATE === "1")
args.push(
"-DCMAKE_C_COMPILER=clang",
"-DCMAKE_CXX_COMPILER=clang++",
"-DSCRIPTC_LLVM_PROFILE_GENERATE=ON",
);
else args.push("-DSCRIPTC_LLVM_PROFILE_GENERATE=OFF");
return args;
}
Binary file not shown.
+38
View File
@@ -64,6 +64,9 @@ static constexpr size_t MaxPartitions = 64;
// multiple of the usual size limit, in builds with a profile. See
// limitProfileImports().
static constexpr const char *ProfileImportMultiplier = "2";
// The thin link's size limit, in instructions, for a callee it imports into
// a partition that calls it. See limitImports().
static constexpr const char *ImportInstructionLimit = "40";
std::optional<EmitOptions> parseEmitOptions(int Argc, char **Argv) {
EmitOptions Options;
@@ -173,6 +176,39 @@ void limitProfileImports() {
(void)Limited;
}
// The thin link imports a callee of up to 100 instructions, LLVM's default,
// into every partition that calls it, and each partition then optimizes and
// compiles its imported copies again. On tsc-ts (64 partitions) a limit of 40
// takes about 7% off the helper's time, and the program runs as fast; 30 and
// below made it run 1-8% slower. The limit is a process-wide option; the
// helper sets it once.
void limitImports() {
static const bool Limited = [] {
if (cl::Option *Option =
cl::getRegisteredOptions().lookup("import-instr-limit"))
Option->addOccurrence(0, "import-instr-limit", ImportInstructionLimit);
return true;
}();
(void)Limited;
}
// Drops the names of a partition's struct types before its summary is
// written. Every partition declares the program's types under the same
// names, and a thin link loads the importing partition and the partitions
// it imports from into one context, which tells same-named types apart by
// appending a counter that runs across the whole link. An edit that adds a
// type anywhere shifts the counter, so the module after importing, the
// object cache key, changed in partitions whose code had not. Unnamed types
// carry no such suffix; importing still matches them by their bodies.
struct UnnameStructTypes : PassInfoMixin<UnnameStructTypes> {
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
for (StructType *Type : M.getIdentifiedStructTypes())
Type->setName("");
return PreservedAnalyses::all();
}
static bool isRequired() { return true; }
};
// How the --profile-use profile matched the functions it annotated, summed
// over partitions: functions that received its counts, functions whose
// control flow changed since it was collected (hash mismatch), and functions
@@ -733,6 +769,7 @@ compileOptimizedPartitions(const EmitOptions &Options,
if (Annotating)
P.countAnnotated(PartitionMatch.Annotated);
ModulePassManager MPM = P.PB.buildThinLTOPreLinkDefaultPipeline(Level);
MPM.addPass(UnnameStructTypes());
MPM.addPass(BitcodeWriterPass(Stream, /*ShouldPreserveUseListOrder=*/false,
/*EmitSummaryIndex=*/true,
/*EmitModuleHash=*/true));
@@ -834,6 +871,7 @@ compileOptimizedPartitions(const EmitOptions &Options,
std::vector<std::string> Names(Count);
for (size_t I = 0; I < Count; ++I)
Names[I] = "partition-" + std::to_string(I);
limitImports();
if (!Options.ProfileUse.empty())
limitProfileImports();
lto::LTO Link(std::move(Config),
+117 -61
View File
@@ -98,7 +98,7 @@ void placeGroups(std::vector<Symbol> &Symbols, ArrayRef<unsigned> Roots,
StringMap<uint64_t> GroupBytes;
for (unsigned I = 0; I < Symbols.size(); ++I) {
const Symbol &S = Symbols[I];
if (S.Kind != SymbolKind::Function)
if (S.Kind != SymbolKind::Function || S.Partition == NoPartition)
continue;
Total += Bytes(S);
StringRef Group = Symbols[Roots[I]].Group;
@@ -119,8 +119,10 @@ void placeGroups(std::vector<Symbol> &Symbols, ArrayRef<unsigned> Roots,
StringMap<uint64_t> KeyBytes;
for (unsigned I = 0; I < Symbols.size(); ++I) {
const Symbol &S = Symbols[I];
if (S.Kind != SymbolKind::Function || S.Partition == NoPartition)
continue;
StringRef Group = Symbols[Roots[I]].Group;
if (S.Kind != SymbolKind::Function || Group.empty())
if (Group.empty())
continue;
uint64_t Chunks = 1;
while (Chunks * Chunk < GroupBytes[Group])
@@ -534,64 +536,6 @@ std::optional<ProgramPartitions> partitionProgramText(StringRef Text,
}
}
// An internal function referenced by exactly one other function, and by
// no global, is a whole-program inlining candidate; keep it with that
// function so its partition can inline it without importing. A function
// body larger than this is past LLVM's inline cost limit even for the only
// call to a local function, so it is placed by its own name. Otherwise a
// program's module initializers, which only the entry point calls, would
// all share the entry point's partition.
constexpr size_t MaxInlinedBodyBytes = 256 * 1024;
constexpr unsigned Shared = ~1u;
std::vector<unsigned> Referrer(Symbols.size(), NoPartition);
for (unsigned I = 0; I < Symbols.size(); ++I) {
const Symbol &S = Symbols[I];
if (S.Kind == SymbolKind::Declaration)
continue;
for (unsigned Ref : S.Refs) {
if (Ref == I)
continue;
if (S.Kind == SymbolKind::Variable || Referrer[Ref] != NoPartition)
Referrer[Ref] = Shared;
else
Referrer[Ref] = I;
}
}
std::vector<unsigned> Roots(Symbols.size());
for (unsigned I = 0; I < Symbols.size(); ++I) {
if (Symbols[I].Kind != SymbolKind::Function)
continue;
unsigned Root = I;
for (unsigned Steps = 0; Steps < 1024; ++Steps) {
const Symbol &S = Symbols[Root];
unsigned Parent = Referrer[Root];
if (!S.Local || S.Body.size() > MaxInlinedBodyBytes ||
Parent == NoPartition || Parent == Shared ||
Symbols[Parent].Kind != SymbolKind::Function || Parent == I)
break;
Root = Parent;
}
Roots[I] = Root;
Symbols[I].Partition = stableHash(Symbols[Root].Name) % Count;
}
placeGroups(Symbols, Roots, Count);
for (const Symbol &S : Symbols) {
if (S.Kind != SymbolKind::Function)
continue;
for (unsigned Ref : S.Refs)
if (Symbols[Ref].Kind == SymbolKind::Variable &&
Symbols[Ref].Partition == NoPartition)
Symbols[Ref].Partition = S.Partition;
}
for (Symbol &S : Symbols)
if (S.Kind == SymbolKind::Variable && S.Partition == NoPartition)
S.Partition = stableHash(S.Name) % Count;
ProgramPartitions Result;
for (const Symbol &S : Symbols)
if (S.Kind != SymbolKind::Declaration && !S.Local)
Result.PublicSymbols.insert(S.Name);
// Metadata nodes are numbered in the emitter's global order, so one added
// node would renumber the references in every partition. Each partition
// instead numbers the nodes it uses in order of first use, which keeps an
@@ -606,10 +550,122 @@ std::optional<ProgramPartitions> partitionProgramText(StringRef Text,
for (StringRef Line : NamedMetadata)
scanReferences(Line, Index, NamedSymbols, NamedRoots);
// An internal definition that no other definition reaches is left out of
// every partition: the optimizer would delete it, and the emitter writes
// variants of helpers that the program never calls. Leaving them out
// shortens every partition's parse, summary and optimization, and since
// placement ignores them too, an edit that adds one changes no partition.
std::vector<char> Live(Symbols.size(), 0);
{
std::vector<unsigned> Work;
auto Reach = [&](unsigned I) {
if (!Live[I]) {
Live[I] = 1;
Work.push_back(I);
}
};
for (unsigned I = 0; I < Symbols.size(); ++I)
if (Symbols[I].Kind != SymbolKind::Declaration && !Symbols[I].Local)
Reach(I);
for (unsigned I : NamedSymbols)
Reach(I);
for (auto &Entry : Metadata)
for (unsigned I : Entry.second.Symbols)
Reach(I);
while (!Work.empty()) {
unsigned I = Work.back();
Work.pop_back();
for (unsigned Ref : Symbols[I].Refs)
Reach(Ref);
}
}
// An internal definition reached from exactly one other definition is an
// inlining candidate of it, or data only it uses; keep it with that
// definition so its partition can inline it without importing, and so a
// helper an edit adds lands in the partition of the code that uses it. A
// chain through a global continues to the function that uses the global.
// A function body larger than this is past LLVM's inline cost limit even
// for the only call to a local function, so it is placed by its own name.
// A chain stops where it would leave a function's source-module group:
// module initializers, which only the entry point calls, keep their own
// partitions instead of all sharing the entry point's.
constexpr size_t MaxInlinedBodyBytes = 256 * 1024;
constexpr unsigned Shared = ~1u;
std::vector<unsigned> Referrer(Symbols.size(), NoPartition);
for (unsigned I = 0; I < Symbols.size(); ++I) {
const Symbol &S = Symbols[I];
if (S.Kind == SymbolKind::Declaration || !Live[I])
continue;
for (unsigned Ref : S.Refs) {
if (Ref == I)
continue;
Referrer[Ref] = Referrer[Ref] == NoPartition ? I : Shared;
}
}
auto Follows = [&](unsigned Child, unsigned Parent) {
const Symbol &S = Symbols[Child];
if (!S.Local || Parent == NoPartition || Parent == Shared ||
Symbols[Parent].Kind == SymbolKind::Declaration)
return false;
if (S.Kind == SymbolKind::Function &&
(S.Body.size() > MaxInlinedBodyBytes ||
(Symbols[Parent].Kind == SymbolKind::Function && !S.Group.empty() &&
S.Group != Symbols[Parent].Group)))
return false;
return true;
};
std::vector<unsigned> Roots(Symbols.size());
for (unsigned I = 0; I < Symbols.size(); ++I) {
if (Symbols[I].Kind == SymbolKind::Declaration || !Live[I])
continue;
unsigned Root = I;
for (unsigned Steps = 0; Steps < 1024; ++Steps) {
unsigned Parent = Referrer[Root];
if (!Follows(Root, Parent) || Parent == I)
break;
Root = Parent;
}
// A function whose chain ends at a global that is not itself placed
// with a function (a table many functions use) is placed by its own
// name, so the functions of one table spread over the partitions.
if (Symbols[I].Kind == SymbolKind::Function &&
Symbols[Root].Kind != SymbolKind::Function)
Root = I;
Roots[I] = Root;
if (Symbols[I].Kind == SymbolKind::Function)
Symbols[I].Partition = stableHash(Symbols[Root].Name) % Count;
}
placeGroups(Symbols, Roots, Count);
// A global follows the function its chain ends at, then the first
// function that references it, then its own name.
for (unsigned I = 0; I < Symbols.size(); ++I)
if (Symbols[I].Kind == SymbolKind::Variable && Live[I] &&
Symbols[Roots[I]].Kind == SymbolKind::Function)
Symbols[I].Partition = Symbols[Roots[I]].Partition;
for (unsigned I = 0; I < Symbols.size(); ++I) {
const Symbol &S = Symbols[I];
if (S.Kind != SymbolKind::Function || !Live[I])
continue;
for (unsigned Ref : S.Refs)
if (Symbols[Ref].Kind == SymbolKind::Variable &&
Symbols[Ref].Partition == NoPartition)
Symbols[Ref].Partition = S.Partition;
}
for (unsigned I = 0; I < Symbols.size(); ++I)
if (Symbols[I].Kind == SymbolKind::Variable && Live[I] &&
Symbols[I].Partition == NoPartition)
Symbols[I].Partition = stableHash(Symbols[I].Name) % Count;
ProgramPartitions Result;
for (const Symbol &S : Symbols)
if (S.Kind != SymbolKind::Declaration && !S.Local)
Result.PublicSymbols.insert(S.Name);
Result.Sources.resize(Count);
std::vector<std::vector<unsigned>> Owned(Count);
for (unsigned I = 0; I < Symbols.size(); ++I)
if (Symbols[I].Kind != SymbolKind::Declaration)
if (Symbols[I].Kind != SymbolKind::Declaration && Live[I])
Owned[Symbols[I].Partition].push_back(I);
auto Assemble = [&](unsigned P) {
+9 -5
View File
@@ -24,11 +24,15 @@ struct ProgramPartitions {
// more partitions, functions under a "; scriptc-group <key>" line are placed
// with the other functions of that source-module group, which is divided
// into chunks when it is larger than the mean partition or 1 MiB; other
// functions are placed by a stable hash of their name. An internal function referenced by exactly one other function stays
// with that function unless its body is too large to inline, and a global
// stays with the first function that references it. Returns nullopt for any
// construct outside the emitter's narrow top-level grammar; callers then
// split a parsed module.
// functions are placed by a stable hash of their name. An internal
// definition referenced by exactly one other definition stays with it, also
// through a global, unless it is a function whose body is too large to
// inline or that would join a function of another source-module group; a
// global otherwise stays with the first function that references it.
// Internal definitions that no non-internal definition, named metadata or
// metadata node reaches are left out of every partition. Returns nullopt
// for any construct outside the emitter's narrow top-level grammar; callers
// then split a parsed module.
std::optional<ProgramPartitions> partitionProgramText(llvm::StringRef Text,
unsigned Count);
+1
View File
@@ -16,6 +16,7 @@
"test:ts7": "node scripts/test-ts7.mjs",
"test:checker-identity": "node scripts/checker-identity.mjs",
"generate:ts7-ast": "node scripts/generate-ts7-ast-schema.mjs",
"generate:ir-fields": "node scripts/generate-ir-fields.mjs",
"test:fetch-conformance": "vitest run tests/harness/fetch-conformance.test.ts",
"test:test262": "tsx tests/test262/run.ts",
"test:test262:fetch": "node tests/test262/fetch.mjs",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-darwin-arm64",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for darwin-arm64",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-darwin-x64",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for darwin-x64",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-linux-arm64-gnu",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for linux-arm64-gnu",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-linux-arm64-musl",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for linux-arm64-musl",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-linux-x64-gnu",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for linux-x64-gnu",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-linux-x64-musl",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for linux-x64-musl",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@scriptc/cli-win32-x64-msvc",
"version": "0.4.4",
"version": "0.4.5",
"description": "Native scriptc compiler for win32-x64-msvc",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "scriptc",
"version": "0.4.4",
"version": "0.4.5",
"description": "Compile ordinary TypeScript and JavaScript to small, fast native executables and WebAssembly modules that run without Node.js",
"license": "Apache-2.0",
"homepage": "https://scriptc.dev",
+1
View File
@@ -49,6 +49,7 @@ export function relocateToolchain(manifest, sourceDirectory, destinationDirector
"declarations",
"comptime",
"wasi_node_runner",
"lib_diagnostics",
]) {
if (typeof relocated[name] === "string") relocated[name] = pathFrom(relocated[name]);
}
+2
View File
@@ -141,6 +141,7 @@ async function tryFastPath(): Promise<number | null> {
...(optimization === "dev" || optimization === "speed" ? { optimization } : {}),
...(values.strip ? { strip: true as const } : {}),
...(values["detached-exit"] ? { detachedExit: true as const } : {}),
...(values["cpu-dispatch"] === true ? { cpuDispatch: true as const } : {}),
...(checker === undefined ? {} : { checker }),
npmStatic,
// Mirrors the full compiler's key: shape inference's overlay is opt-in
@@ -225,6 +226,7 @@ async function coverageFastPath(
values.strip ||
values["detached-exit"] ||
values["target-cpu"] !== undefined ||
values["cpu-dispatch"] !== undefined ||
values.lib ||
values.profile !== undefined ||
values.ffi !== undefined ||
+2
View File
@@ -10,6 +10,7 @@ import {
mergeProfiles,
resolveProvenanceSources,
sourceTargetPlatform,
typePatches,
warmNativeCaches,
} from "@scriptc/compiler";
import { runCli } from "./command.js";
@@ -39,6 +40,7 @@ process.exitCode = await runCli(process.argv.slice(2), {
sourceTargetPlatform,
warmNativeCaches,
mergeProfiles,
typePatches,
run: (binary) =>
new Promise<number>((resolveExit) => {
let child;
+82
View File
@@ -0,0 +1,82 @@
import { execFile } from "node:child_process";
import { createRequire } from "node:module";
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { promisify } from "node:util";
import { expect, test } from "vitest";
const execFileAsync = promisify(execFile);
const require = createRequire(import.meta.url);
const repoRoot = join(import.meta.dirname, "../../..");
const cliEntry = join(repoRoot, "packages/cli/src/main.ts");
const bootstrapEntry = join(repoRoot, "packages/cli/dist/bootstrap.js");
const tsxLoader = join(dirname(require.resolve("tsx/package.json")), "dist/loader.mjs");
const program = `function mix(a: Float64Array, b: Float64Array, k: number): number {
let s = 0;
for (let i = 0; i < a.length; i++) s += a[i]! * k + b[i]! / (i + 1);
return s;
}
const a = new Float64Array(4096);
const b = new Float64Array(4096);
for (let i = 0; i < a.length; i++) {
a[i] = ((i * 7919) % 1000) / 7 - 50;
b[i] = 1 / (i + 3);
}
let total = 0;
for (let r = 0; r < 32; r++) total += mix(a, b, r * 0.1);
console.log(total, [3, 1, 2].map((x) => mix(a.subarray(x), b, x)).join(" "));
`;
test.runIf(process.platform === "linux" && process.arch === "x64")(
"--cpu-dispatch builds one executable that matches Node at every level",
async () => {
const dir = await mkdtemp(join("/tmp", "scriptc-cpu-dispatch-"));
const entry = join(dir, "main.ts");
const outPath = join(dir, "program");
const llvmPath = join(dir, "main.ll");
const env = { ...process.env, SCRIPTC_CACHE_DIR: join(dir, "cache") };
const build = async (args: string[], bootstrap = false): Promise<string> => {
await execFileAsync(
process.execPath,
[
...(bootstrap ? [bootstrapEntry] : ["--import", tsxLoader, cliEntry]),
"build",
entry,
"-o",
outPath,
...args,
],
{ env, maxBuffer: 4 * 1024 * 1024 },
);
return readFile(llvmPath, "utf8");
};
const run = async (level?: string): Promise<string> =>
(
await execFileAsync(outPath, [], {
env: { ...process.env, ...(level === undefined ? {} : { SCRIPTC_CPU_LEVEL: level }) },
})
).stdout;
try {
await writeFile(entry, program);
const expected = `${(await execFileAsync(process.execPath, [entry])).stdout}`;
const plain = await build(["--optimization=speed"]);
expect(plain).not.toContain("@sc_cpu_level");
const dispatching = await build(["--optimization=speed", "--cpu-dispatch"]);
expect(dispatching).toMatch(/^define internal double @sc_bf_mix\.v3\(/m);
for (const level of [undefined, "0", "baseline", "3", "x86-64-v3"])
expect(await run(level), `SCRIPTC_CPU_LEVEL=${level}`).toBe(expected);
// The bootstrap's cached route keeps the two builds apart.
expect(await build(["--optimization=speed"], true)).toBe(plain);
expect(await build(["--optimization=speed", "--cpu-dispatch"], true)).toBe(dispatching);
expect(await build(["--cpu-dispatch"])).toContain("@sc_cpu_level_init()");
expect(await run("0")).toBe(expected);
expect(await build(["--target-cpu=x86-64-v3", "--cpu-dispatch"])).not.toContain(
"@sc_cpu_level",
);
} finally {
await rm(dir, { recursive: true, force: true });
}
},
240_000,
);
+4
View File
@@ -53,6 +53,7 @@ function fixture() {
dsymutil: "dsymutil",
comptime: "../lib/comptime",
wasi_node_runner: "../lib/wasi/cli/wasi-runner.js",
lib_diagnostics: "../lib/lib-diagnostics.json",
};
writeFileSync(binary + ".json", JSON.stringify(toolchain));
const helpers = [
@@ -93,6 +94,9 @@ test("installs a direct executable and relocatable references to platform assets
expect(resolve(dirname(installed), manifest.wasi_node_runner)).toBe(
join(platform, "wasi/cli/wasi-runner.js"),
);
expect(resolve(dirname(installed), manifest.lib_diagnostics)).toBe(
join(platform, "lib-diagnostics.json"),
);
expect(resolve(dirname(installed), manifest.runtime_packs[0].path)).toBe(
join(platform, "runtime"),
);
+2 -2
View File
@@ -72,7 +72,7 @@ describe.runIf(supported)("macOS arm64 native link info", () => {
minimum_os: "14.0",
},
program: { object, entry_symbol: "main" },
runtime_abi: { version: 43, marker: "scr_runtime_abi_v43" },
runtime_abi: { version: 47, marker: "scr_runtime_abi_v47" },
runtime_pack: {
kind: "precompiled",
package: "@scriptc/runtime-darwin-arm64",
@@ -165,6 +165,6 @@ describe.runIf(supported)("macOS arm64 native link info", () => {
() => null,
(failure: { stderr?: string }) => failure,
);
expect(error?.stderr).toContain("scr_runtime_abi_v43");
expect(error?.stderr).toContain("scr_runtime_abi_v47");
});
});
+1
View File
@@ -48,6 +48,7 @@ describe("output option compatibility", () => {
[{ emit: "llvm", strip: true }, /strip/],
[{ emit: "obj", detachedExit: true }, /detached-exit/],
[{ emit: "llvm", detachedExit: true }, /detached-exit/],
[{ emit: "asm", cpuDispatch: true }, /cpu-dispatch/],
[{ emit: "obj", profileGenerate: "/tmp/%p.profraw" }, /profile-generate/],
[{ emit: "llvm", profileUse: "/tmp/a.profdata" }, /profile-use/],
[{ profileGenerate: "/tmp/%p.profraw", profileUse: "/tmp/a.profdata" }, /cannot be combined/],
+16 -3
View File
@@ -63,8 +63,16 @@ test.skipIf(process.platform !== "linux")(
expect(merge.stdout).toBe(`${merged}\n`);
const optimized = join(dir, "optimized");
await scriptc(["build", entry, "--profile-use", merged, "-o", optimized], env);
const fresh = await scriptc(["build", entry, "--profile-use", merged, "-o", optimized], env);
expect((await execFileAsync(optimized, ["1000"])).stdout).toBe("total 167499\n");
// The build reports how the profile matched the program's functions.
expect(fresh.stderr).toMatch(
/^scriptc: profile .*: [1-9]\d* functions annotated, 0 mismatched, \d+ without a record\n$/,
);
expect(fresh.stderr).toContain(`scriptc: profile ${merged}: `);
// A build from the cache reports the same match.
const again = await scriptc(["build", entry, "--profile-use", merged, "-o", optimized], env);
expect(again.stderr).toBe(fresh.stderr);
// A sparse profile leaves out the runtime functions the runs never
// reached.
@@ -77,10 +85,15 @@ test.skipIf(process.platform !== "linux")(
await scriptc(["build", entry, "--profile-use", sparse, "-o", optimized], env);
expect((await execFileAsync(optimized, ["1000"])).stdout).toBe("total 167499\n");
// A profile from an older version of the program still builds it.
// A profile from an older version of the program still builds it. The
// edited function no longer matches its counts, and the build warns.
await writeFile(entry, PROGRAM + 'console.log("edited");\n');
await scriptc(["build", entry, "--profile-use", merged, "-o", optimized], env);
const stale = await scriptc(["build", entry, "--profile-use", merged, "-o", optimized], env);
expect((await execFileAsync(optimized, ["1000"])).stdout).toBe("total 167499\nedited\n");
expect(stale.stderr).toMatch(/ [1-9]\d* mismatched, /);
expect(stale.stderr).toMatch(
/\nscriptc: warning: [1-9]\d* of the \d+ functions .* describes \([\d.]+%\) changed since it was collected and are optimized without their counts; collect the profile again\n$/,
);
} finally {
await rm(dir, { recursive: true, force: true });
}
+3 -1
View File
@@ -50,9 +50,11 @@ test.runIf(process.platform === "linux" && process.arch === "x64")(
const expected = `${(await execFileAsync(process.execPath, [entry])).stdout}`;
const baseline = await build([]);
expect(baseline).not.toContain('"target-cpu"');
// Only --sanitize builds mark the functions for ASan instrumentation.
expect(baseline).not.toContain("sanitize_address");
expect(await build(["--target-cpu=baseline"])).toBe(baseline);
const v3 = await build(["--target-cpu=x86-64-v3"]);
expect(v3).toMatch(/^attributes #0 = \{ sanitize_address "target-cpu"="x86-64-v3" \}$/m);
expect(v3).toMatch(/^attributes #0 = \{ "target-cpu"="x86-64-v3" \}$/m);
if (runsV3) expect((await execFileAsync(outPath)).stdout).toBe(expected);
// The bootstrap's cached route builds without a level.
expect(await build([], true)).toBe(baseline);
@@ -0,0 +1,47 @@
/// <reference path="./assert.d.ts" />
/* node:assert/strict — the same surface with the loose names bound to the
* strict comparisons (equal IS strictEqual, ...), exactly Node's aliasing;
* the module object is callable like assert's. */
declare module "assert/strict" {
function strict(value: unknown, message?: string): void;
namespace strict {
function ok(value: unknown, message?: string): void;
function equal(actual: unknown, expected: unknown, message?: string): void;
function notEqual(actual: unknown, expected: unknown, message?: string): void;
function deepEqual(actual: unknown, expected: unknown, message?: string): void;
function notDeepEqual(actual: unknown, expected: unknown, message?: string): void;
function strictEqual(actual: unknown, expected: unknown, message?: string): void;
function notStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function deepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function notDeepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function partialDeepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function fail(message?: string): never;
function throws(fn: () => unknown, expected?: unknown, message?: string): void;
function doesNotThrow(fn: () => unknown, expected?: unknown, message?: string): void;
function rejects(
fn: (() => Promise<unknown>) | Promise<unknown>,
expected?: unknown,
message?: string,
): Promise<void>;
function doesNotReject(
fn: (() => Promise<unknown>) | Promise<unknown>,
expected?: unknown,
message?: string,
): Promise<void>;
function match(value: string, regExp: RegExp, message?: string): void;
function doesNotMatch(value: string, regExp: RegExp, message?: string): void;
function ifError(value: unknown): void;
const strict: typeof import("assert/strict");
type AssertOptions = import("assert").AssertOptions;
type Assert = import("assert").Assert;
type AssertStrict = import("assert").AssertStrict;
const Assert: typeof import("assert").Assert;
}
export = strict;
}
declare module "node:assert/strict" {
import strict = require("assert/strict");
export = strict;
}
+86
View File
@@ -0,0 +1,86 @@
/// <reference path="./assert-strict.d.ts" />
declare module "assert" {
function assert(value: unknown, message?: string): void;
namespace assert {
interface AssertionErrorOptions {
message?: string | undefined;
actual?: unknown;
expected?: unknown;
operator?: string | undefined;
stackStartFn?: Function | undefined;
diff?: "simple" | "full" | undefined;
}
class AssertionError extends Error {
constructor(options: AssertionErrorOptions);
actual: unknown;
expected: unknown;
generatedMessage: boolean;
code: "ERR_ASSERTION";
operator: string;
}
function ok(value: unknown, message?: string): void;
function strictEqual(actual: unknown, expected: unknown, message?: string): void;
function notStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function deepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function notDeepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function partialDeepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
function equal(actual: unknown, expected: unknown, message?: string): void;
function notEqual(actual: unknown, expected: unknown, message?: string): void;
function deepEqual(actual: unknown, expected: unknown, message?: string): void;
function notDeepEqual(actual: unknown, expected: unknown, message?: string): void;
function fail(message?: string): never;
function throws(fn: () => unknown, expected?: unknown, message?: string): void;
function doesNotThrow(fn: () => unknown, expected?: unknown, message?: string): void;
function rejects(
fn: (() => Promise<unknown>) | Promise<unknown>,
expected?: unknown,
message?: string,
): Promise<void>;
function doesNotReject(
fn: (() => Promise<unknown>) | Promise<unknown>,
expected?: unknown,
message?: string,
): Promise<void>;
function match(value: string, regExp: RegExp, message?: string): void;
function doesNotMatch(value: string, regExp: RegExp, message?: string): void;
function ifError(value: unknown): void;
const strict: typeof import("assert/strict");
interface AssertOptions {
diff?: "simple" | "full" | undefined;
strict?: boolean | undefined;
skipPrototype?: boolean | undefined;
}
type AssertMethodNames =
| "deepEqual"
| "deepStrictEqual"
| "doesNotMatch"
| "doesNotReject"
| "doesNotThrow"
| "equal"
| "fail"
| "ifError"
| "match"
| "notDeepEqual"
| "notDeepStrictEqual"
| "notEqual"
| "notStrictEqual"
| "ok"
| "partialDeepStrictEqual"
| "rejects"
| "strictEqual"
| "throws";
interface Assert extends Pick<typeof assert, AssertMethodNames> {}
interface AssertStrict extends Pick<typeof strict, AssertMethodNames> {}
const Assert: {
new (options?: AssertOptions & { strict?: true | undefined }): AssertStrict;
new (options: AssertOptions): Assert;
};
}
export = assert;
}
declare module "node:assert" {
import assert = require("assert");
export = assert;
}
@@ -0,0 +1,41 @@
/* node:async_hooks — declared surface without lowering: async-hook
* instrumentation is guarded behind env flags in harness code; a reached
* use fences at its site. */
declare module "async_hooks" {
/* AsyncLocalStorage: fiber-carried context snapshots — run/getStore/
* exit/enterWith/disable lower onto the runtime's active-slot machinery
* (als.* libCalls); values cross as dyn values. bind and snapshot bind
* functions to the active context; the options carry the store's
* default value and name. */
export interface AsyncLocalStorageOptions {
defaultValue?: any;
name?: string | undefined;
}
export class AsyncLocalStorage<T = any> {
constructor(options?: AsyncLocalStorageOptions);
static bind<Func extends (...args: any[]) => any>(fn: Func): Func;
static snapshot(): <R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs) => R;
readonly name: string;
run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;
exit<R>(callback: (...args: any[]) => R, ...args: any[]): R;
getStore(): T | undefined;
enterWith(store: T): void;
disable(): void;
}
export interface AsyncHook {
enable(): AsyncHook;
disable(): AsyncHook;
}
export function createHook(callbacks: {
init?: (asyncId: number, type: string, triggerAsyncId: number, resource: unknown) => void;
before?: (asyncId: number) => void;
after?: (asyncId: number) => void;
destroy?: (asyncId: number) => void;
}): AsyncHook;
export function executionAsyncId(): number;
export function triggerAsyncId(): number;
}
declare module "node:async_hooks" {
export * from "async_hooks";
}
+23
View File
@@ -0,0 +1,23 @@
/* node:buffer — the module spelling of the Buffer/atob/btoa globals.
* Buffer re-exports the GLOBAL declaration, so an imported binding
* resolves to the same symbol the lowerings already answer for (and
* third-party .d.ts files that `import { Buffer } from "node:buffer"` —
* file-entry-cache in a typed-JS source graph — typecheck). */
declare module "buffer" {
export function isAscii(input: ArrayBuffer | ArrayBufferView): boolean;
export function isUtf8(input: ArrayBuffer | ArrayBufferView): boolean;
export function transcode(source: Uint8Array, fromEncoding: string, toEncoding: string): Buffer;
export function atob(data: string): string;
export function btoa(data: string): string;
export const kMaxLength: number;
export const kStringMaxLength: number;
export const Buffer: BufferConstructor;
export type Blob = globalThis.Blob;
export type File = globalThis.File;
export const Blob: typeof globalThis.Blob;
export const File: typeof globalThis.File;
}
declare module "node:buffer" {
export * from "buffer";
}
@@ -0,0 +1,223 @@
/* node:child_process — the synchronous slice: spawnSync(command, args?)
* runs the child to completion (posix_spawn + waitpid) with stdout/stderr
* captured as utf8 strings. `status` is the exit code, or null when the
* child died to a signal OR could not be spawned at all (nonexistent
* binary, permission denied) — Node reports spawn failure through the
* result's `error` property, which this surface does not carry, and types
* stdout/stderr null there where scriptc returns "" (SEMANTICS.md).
* No shell, no options object: the command runs directly (PATH-searched,
* like Node). */
declare module "child_process" {
export interface SpawnSyncReturns {
readonly status: number | null;
readonly stdout: string;
readonly stderr: string;
/* The termination signal's name ("SIGTERM", ...) when a signal
* killed the child (a timeout's killSignal included), null otherwise
* — Node's shape. */
readonly signal: string | null;
/* Node's spawn-failure carrier: a real Error ("spawnSync <file>
* ENOENT", `code` stamped) when the spawn itself failed — status is
* null and both outputs "" then — or ETIMEDOUT after a timeout kill;
* undefined otherwise. */
readonly error?: Error;
}
/* scriptc always captures utf8 strings; pass { encoding: "utf8" }
* whenever stdout/stderr is READ so plain Node agrees (without it Node
* hands Buffers). The other supported options: timeout (ms — sends
* killSignal at the deadline and the result carries error: ETIMEDOUT +
* the signal, never a throw), killSignal (a signal NAME literal),
* stdio ("ignore"/"inherit"/"pipe" or a 3-tuple of those — captures
* read "" for non-piped streams), env (replaces the child's
* environment), and windowsHide (a POSIX no-op). */
export function spawnSync(
command: string,
args?: string[],
options?: {
encoding?: "utf8" | "utf-8";
timeout?: number;
killSignal?: string;
stdio?: "pipe" | "ignore" | "inherit" | ("pipe" | "ignore" | "inherit")[];
env?: { [k: string]: string | undefined };
windowsHide?: boolean;
},
): SpawnSyncReturns;
/* The asynchronous slice: spawn with stdio "ignore"/"inherit"/fd/"pipe"
* tuples (piped stdin is writable through child.stdin; piped stdout/stderr
* deliver through child.stdout/stderr) and the terminal events. "exit"
* fires once with the exit code, or
* null when the child died to a signal; "error" fires ONLY when the
* child could not be spawned at all (Node's split: a spawn failure
* emits "error" and never "exit"). "close" fires after exit/error and
* every piped stdio handle reaches EOF. Exit/close listeners may take
* Node's code and signal parameters. `on`/`once` return void here (Node
* returns the child; chaining is fenced). The event loop keeps the process
* alive until every spawned child is reaped, like Node — reaping polls at
* loop quiescence (SEMANTICS.md documents the divergence). An "error"
* event with no registered listener prints the error and exits 1,
* exactly the unhandled-'error' EventEmitter behavior. */
export interface ChildStdin {
readonly writable: boolean;
write(chunk: string | Uint8Array): boolean;
end(): void;
destroy(): void;
on(event: "drain" | "finish", listener: () => void): void;
on(event: "error", listener: (err: Error) => void): void;
on(event: string, listener: (...args: any[]) => void): void;
once(event: "drain" | "finish", listener: () => void): void;
once(event: "error", listener: (err: Error) => void): void;
once(event: string, listener: (...args: any[]) => void): void;
}
export interface ChildProcess extends Disposable {
ref(): void;
on(event: "spawn", listener: () => void): this;
once(event: "spawn", listener: () => void): this;
/* The exit listener may also take Node's second parameter — the
* terminating signal's name, null for a normal exit. */
on(event: "exit", listener: (code: number | null, signal: string | null) => void): this;
on(event: "close", listener: (code: number | null, signal: string | null) => void): this;
on(event: "error", listener: (err: Error) => void): this;
once(event: "exit", listener: (code: number | null, signal: string | null) => void): this;
once(event: "close", listener: (code: number | null, signal: string | null) => void): this;
once(event: "error", listener: (err: Error) => void): this;
on(event: "message", listener: (message: any) => void): this;
on(event: "disconnect", listener: () => void): this;
once(event: "message", listener: (message: any) => void): this;
once(event: "disconnect", listener: () => void): this;
/* The lifecycle members, Node's exact shapes: pid is undefined exactly
* when the spawn failed; exitCode is null while running, the code
* after a normal exit, null for a signal death, and -errno once a
* spawn failure's "error" event has fired; kill resolves signal names
* through Node's table (unknown names throw the Unknown signal
* TypeError), answers true when the signal was sent, false once the
* child was reaped (or never spawned), and sets `killed` on success;
* unref() drops the child from the event loop's keep-alive set (it is
* still reaped while the loop runs for other reasons — SEMANTICS.md
* has the reap story). */
readonly pid: number | undefined;
readonly exitCode: number | null;
readonly killed: boolean;
kill(signal?: string | number): boolean;
unref(): void;
readonly connected: boolean;
send(message: object, callback?: (error: Error | null) => void): boolean;
disconnect(): void;
[Symbol.dispose](): void;
/* The piped streams — non-null exactly when the matching stdio slot
* was "pipe" (Node's shape). */
readonly stdin: ChildStdin | null;
readonly stdout: NodeJS.ReadableStream | null;
readonly stderr: NodeJS.ReadableStream | null;
}
export interface SpawnOptions {
/* The 3-tuple form admits number fds in the stdout/stderr slots —
* openSync results dup2'd into the child (the daemon-log idiom
* ["ignore", logFd, logFd]) — and "pipe" there too (child.stdout/
* child.stderr streams); "pipe" in the stdin slot exposes
* child.stdin. */
stdio?: "ignore" | "inherit" | "pipe" | ("ignore" | "inherit" | "pipe" | number)[];
/* detached gives the child its own session and process group
* (POSIX_SPAWN_SETSID); env REPLACES the child environment; cwd
* sets its working directory; windowsHide is a POSIX no-op; shell
* runs the complete command string through /bin/sh or cmd.exe. */
detached?: boolean;
env?: { [k: string]: string | undefined };
cwd?: string;
windowsHide?: boolean;
shell?: boolean;
}
export function spawn(command: string, args?: string[], options?: SpawnOptions): ChildProcess;
export function spawn(command: string, options?: SpawnOptions): ChildProcess;
export function fork(
modulePath: string | URL,
args?: string[],
options?: {
cwd?: string;
env?: { [k: string]: string | undefined };
execArgv?: string[];
silent?: boolean;
stdio?: "pipe" | "ignore" | "inherit" | ("pipe" | "ignore" | "inherit" | "ipc")[];
serialization?: "json" | "advanced";
windowsHide?: boolean;
},
): ChildProcess;
/* The synchronous exec pair: execFileSync runs a file directly (no
* shell), execSync runs a command through /bin/sh -c. Both capture
* stdout as a utf8 string (pass { encoding: "utf8" } so plain Node
* agrees — without it Node returns a Buffer) and THROW on a non-zero
* exit / signal death — the Error's message is Node's "Command failed:
* <cmd>" (with the captured stderr appended). Supported options:
* encoding ("utf8"), cwd, env (REPLACES the child environment), input
* (fed to stdin), timeout (ms — SIGTERMs the child, then throws
* ETIMEDOUT), stdio ("pipe"/"ignore" or a 3-tuple of those — the
* default captures stderr AND echoes it to the parent, like Node), and
* maxBuffer (accepted, not enforced). Node's status/stdout/stderr error
* properties are not carried (SEMANTICS.md). */
interface ExecSyncOptions {
encoding?: "utf8" | "utf-8";
cwd?: string;
env?: { [k: string]: string | undefined };
input?: string;
timeout?: number;
stdio?: "pipe" | "ignore" | "inherit" | ("pipe" | "ignore" | "inherit")[];
maxBuffer?: number;
killSignal?: string;
windowsHide?: boolean;
shell?: boolean;
}
/* The named options interface for the string-encoding exec form —
* @types/node's ExecFileSyncOptionsWithStringEncoding, narrowed to the
* honestly-implemented members. VALUES of this type are a real record
* (type-mapper.ts interns the shape), so a typed const or a runner function's
* options parameter flows to execFileSync at runtime — the windows-ca
* command-runner idiom. */
export interface ExecFileSyncOptionsWithStringEncoding {
encoding: "utf8" | "utf-8";
cwd?: string;
input?: string;
timeout?: number;
stdio?: "pipe" | "ignore" | "inherit" | ("pipe" | "ignore" | "inherit")[];
maxBuffer?: number;
windowsHide?: boolean;
}
export function execFileSync(file: string, args?: string[], options?: ExecSyncOptions): string;
export function execSync(command: string, options?: ExecSyncOptions): string;
export type ExecFileCallback = (error: Error | null, stdout: string, stderr: string) => void;
/* The callback form starts an asynchronous child and captures utf8
* stdout/stderr. The no-callback overload remains for util.promisify's
* static target recognition; reached no-callback calls still fence. */
export function execFile(file: string, callback: ExecFileCallback): ChildProcess;
export function execFile(
file: string,
args: string[] | null,
callback: ExecFileCallback,
): ChildProcess;
export function execFile(
file: string,
args: string[] | null,
options: ExecSyncOptions,
callback: ExecFileCallback,
): ChildProcess;
export function execFile(
file: string,
args?: string[] | null,
options?: ExecSyncOptions,
): unknown;
/* The async shell form. The callback forms lower like execFile's, with
* the command line run by /bin/sh -c, and util.promisify recognizes it
* statically, as it does execFile; reached calls without a callback
* fence at their site. */
export function exec(
command: string,
options?: ExecSyncOptions | ((error: Error | null, stdout: string, stderr: string) => void),
callback?: (error: Error | null, stdout: string, stderr: string) => void,
): ChildProcess;
}
declare module "node:child_process" {
export * from "child_process";
}
+17
View File
@@ -0,0 +1,17 @@
/* node:cluster — the primary-probe slice. A compiled binary never runs
* as a cluster worker (cluster forks the node binary itself — the
* mechanism is na for compiled programs), so isPrimary lowers to `true`
* and isWorker to `false`; everything else is undeclared. */
declare module "cluster" {
const cluster: {
readonly isPrimary: boolean;
readonly isMaster: boolean;
readonly isWorker: boolean;
};
export = cluster;
}
declare module "node:cluster" {
import cluster = require("cluster");
export = cluster;
}
+15
View File
@@ -0,0 +1,15 @@
/* node:constants (deprecated, DEP0008) — one frozen object: os.constants'
* dlopen, errno, priority and signals groups, fs.constants, and
* crypto.constants. A platform's missing constant reads as undefined. */
declare module "constants" {
const constants: { readonly [name: string]: number } & {
readonly defaultCoreCipherList: string;
readonly defaultCipherList: string;
};
export = constants;
}
declare module "node:constants" {
import constants = require("constants");
export = constants;
}
+837
View File
@@ -0,0 +1,837 @@
/// <reference path="./stream.d.ts" />
/// <reference path="./tls.d.ts" />
/* node:crypto: the static hashing/MAC/random/key-derivation utility slice. */
declare module "crypto" {
import { Transform } from "stream";
export type KeyObjectType = "secret" | "public" | "private";
export interface JsonWebKey {
crv?: string;
d?: string;
dp?: string;
dq?: string;
e?: string;
k?: string;
kty?: string;
n?: string;
p?: string;
q?: string;
qi?: string;
x?: string;
y?: string;
[key: string]: unknown;
}
export interface JwkKeyExportOptions {
format: "jwk";
}
export interface KeyExportOptions {
format?: "buffer" | undefined;
}
export type KeyFormat = "pem" | "der" | "jwk";
export interface AsymmetricKeyExportOptions<T extends KeyFormat> {
type: "pkcs1" | "spki" | "pkcs8" | "sec1";
format: T;
cipher?: string | undefined;
passphrase?: string | Buffer | undefined;
}
export interface AsymmetricKeyDetails {
modulusLength?: number;
publicExponent?: bigint;
namedCurve?: string;
}
/* Secret keys, and RSA and EC private and public keys. */
export class KeyObject {
private constructor();
type: KeyObjectType;
symmetricKeySize?: number;
asymmetricKeyType?: string;
asymmetricKeyDetails?: AsymmetricKeyDetails;
export(options: AsymmetricKeyExportOptions<"pem">): string | Buffer;
export(options: AsymmetricKeyExportOptions<"der">): Buffer;
export(options?: KeyExportOptions): Buffer;
export(options: JwkKeyExportOptions): JsonWebKey;
equals(otherKeyObject: KeyObject): boolean;
}
export interface PrivateKeyInput {
key: string | Buffer;
format?: "pem" | "der" | undefined;
type?: "pkcs1" | "pkcs8" | "sec1" | undefined;
encoding?: string | undefined;
passphrase?: string | Buffer | undefined;
}
export interface PublicKeyInput {
key: string | Buffer;
format?: "pem" | "der" | undefined;
type?: "pkcs1" | "spki" | undefined;
encoding?: string | undefined;
}
export interface JsonWebKeyInput {
key: JsonWebKey;
format: "jwk";
}
export function createPrivateKey(
key: PrivateKeyInput | string | Buffer | JsonWebKeyInput,
): KeyObject;
export function createPublicKey(
key: PublicKeyInput | string | Buffer | KeyObject | JsonWebKeyInput,
): KeyObject;
export interface KeyPairKeyObjectResult {
publicKey: KeyObject;
privateKey: KeyObject;
}
export interface KeyPairSyncResult<T1 extends string | Buffer, T2 extends string | Buffer> {
publicKey: T1;
privateKey: T2;
}
export interface RSAKeyPairKeyObjectOptions {
modulusLength: number;
publicExponent?: number | undefined;
}
export interface ECKeyPairKeyObjectOptions {
namedCurve: string;
}
export interface RSAKeyPairOptions<PubF extends KeyFormat, PrivF extends KeyFormat> {
modulusLength: number;
publicExponent?: number | undefined;
publicKeyEncoding: { type: "pkcs1" | "spki"; format: PubF };
privateKeyEncoding: {
type: "pkcs1" | "pkcs8";
format: PrivF;
cipher?: string | undefined;
passphrase?: string | undefined;
};
}
export interface ECKeyPairOptions<PubF extends KeyFormat, PrivF extends KeyFormat> {
namedCurve: string;
publicKeyEncoding: { type: "pkcs1" | "spki"; format: PubF };
privateKeyEncoding: {
type: "sec1" | "pkcs8";
format: PrivF;
cipher?: string | undefined;
passphrase?: string | undefined;
};
}
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "rsa",
options: RSAKeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(
type: "ec",
options: ECKeyPairKeyObjectOptions,
): KeyPairKeyObjectResult;
export interface ED25519KeyPairOptions<PubF extends KeyFormat, PrivF extends KeyFormat> {
publicKeyEncoding: { type: "spki"; format: PubF };
privateKeyEncoding: {
type: "pkcs8";
format: PrivF;
cipher?: string | undefined;
passphrase?: string | undefined;
};
}
export function generateKeyPairSync(
type: "ed25519",
options: ED25519KeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "ed25519",
options: ED25519KeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(type: "ed25519", options?: {}): KeyPairKeyObjectResult;
export interface X25519KeyPairOptions<PubF extends KeyFormat, PrivF extends KeyFormat> {
publicKeyEncoding: { type: "spki"; format: PubF };
privateKeyEncoding: {
type: "pkcs8";
format: PrivF;
cipher?: string | undefined;
passphrase?: string | undefined;
};
}
export function generateKeyPairSync(
type: "x25519",
options: X25519KeyPairOptions<"pem", "pem">,
): KeyPairSyncResult<string, string>;
export function generateKeyPairSync(
type: "x25519",
options: X25519KeyPairOptions<"der", "der">,
): KeyPairSyncResult<Buffer, Buffer>;
export function generateKeyPairSync(type: "x25519", options?: {}): KeyPairKeyObjectResult;
export function generateKeyPair(
type: "x25519",
options: {} | undefined,
callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void,
): void;
export function generateKeyPair(
type: "ed25519",
options: {} | undefined,
callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void,
): void;
export function generateKeyPair(
type: "rsa",
options: RSAKeyPairKeyObjectOptions,
callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void,
): void;
export function generateKeyPair(
type: "ec",
options: ECKeyPairKeyObjectOptions,
callback: (err: Error | null, publicKey: KeyObject, privateKey: KeyObject) => void,
): void;
export interface SigningOptions {
padding?: number | undefined;
saltLength?: number | undefined;
dsaEncoding?: "der" | "ieee-p1363" | undefined;
}
export interface SignPrivateKeyInput extends PrivateKeyInput, SigningOptions {}
export interface SignKeyObjectInput extends SigningOptions {
key: KeyObject;
}
export interface VerifyPublicKeyInput extends PublicKeyInput, SigningOptions {}
export interface VerifyKeyObjectInput extends SigningOptions {
key: KeyObject;
}
export function diffieHellman(options: { privateKey: KeyObject; publicKey: KeyObject }): Buffer;
export function diffieHellman(
options: { privateKey: KeyObject; publicKey: KeyObject },
callback: (err: Error | null, secret: Buffer) => void,
): void;
export function sign(
algorithm: string | null | undefined,
data: ArrayBufferView,
key: KeyObject | string | Buffer | SignKeyObjectInput | SignPrivateKeyInput,
): Buffer;
export function verify(
algorithm: string | null | undefined,
data: ArrayBufferView,
key: KeyObject | string | Buffer | VerifyKeyObjectInput | VerifyPublicKeyInput,
signature: ArrayBufferView,
): boolean;
/* Sign and Verify accumulate update() data; they are not usable as
* writable streams. */
export class Sign {
private constructor();
update(data: string | ArrayBufferView): this;
update(data: string, inputEncoding: Encoding): this;
sign(
privateKey: KeyObject | string | Buffer | SignKeyObjectInput | SignPrivateKeyInput,
): Buffer;
sign(
privateKey: KeyObject | string | Buffer | SignKeyObjectInput | SignPrivateKeyInput,
outputFormat: BinaryToTextEncoding,
): string;
}
export class Verify {
private constructor();
update(data: string | ArrayBufferView): this;
update(data: string, inputEncoding: Encoding): this;
verify(
object: KeyObject | string | Buffer | VerifyKeyObjectInput | VerifyPublicKeyInput,
signature: ArrayBufferView,
): boolean;
verify(
object: KeyObject | string | Buffer | VerifyKeyObjectInput | VerifyPublicKeyInput,
signature: string,
signatureEncoding?: BinaryToTextEncoding,
): boolean;
}
export function createSign(algorithm: string): Sign;
export function createVerify(algorithm: string): Verify;
export function createSecretKey(key: ArrayBufferView | ArrayBufferLike): KeyObject;
export function createSecretKey(key: string, encoding: BufferEncoding): KeyObject;
export function generateKeySync(type: "hmac" | "aes", options: { length: number }): KeyObject;
export function generateKey(
type: "hmac" | "aes",
options: { length: number },
callback: (err: Error | null, key: KeyObject) => void,
): void;
export interface RandomUUIDOptions {
disableEntropyCache?: boolean | undefined;
}
export function randomUUID(options?: RandomUUIDOptions): string;
export function randomUUIDv7(options?: RandomUUIDOptions): string;
export function randomBytes(size: number): Buffer;
export type BinaryToTextEncoding = "base64" | "base64url" | "hex" | "binary";
export type CharacterEncoding = "utf8" | "utf-8" | "utf16le" | "utf-16le" | "latin1";
export type LegacyCharacterEncoding = "ascii" | "binary" | "ucs2" | "ucs-2";
export type Encoding = BinaryToTextEncoding | CharacterEncoding | LegacyCharacterEncoding;
export interface HashOptions {
outputLength?: number | undefined;
}
/* Hash and Hmac are Transforms: written chunks update the digest, which
* the readable side delivers once the writable side ends. */
export interface Hash extends Transform {
copy(options?: HashOptions): Hash;
update(data: string | ArrayBufferView): Hash;
update(data: string, inputEncoding: Encoding): Hash;
digest(): Buffer;
digest(encoding: BinaryToTextEncoding): string;
}
export interface Hmac extends Transform {
update(data: string | ArrayBufferView): Hmac;
update(data: string, inputEncoding: Encoding): Hmac;
digest(): Buffer;
digest(encoding: BinaryToTextEncoding): string;
}
export function createHash(algorithm: string, options?: HashOptions): Hash;
export function createHmac(
algorithm: string,
key: BinaryLike | KeyObject,
options?: { encoding?: BufferEncoding | undefined },
): Hmac;
export interface OneShotDigestOptions {
outputEncoding?: BinaryToTextEncoding | "buffer" | undefined;
outputLength?: number | undefined;
}
export interface OneShotDigestOptionsWithStringEncoding extends OneShotDigestOptions {
outputEncoding?: BinaryToTextEncoding | undefined;
}
export interface OneShotDigestOptionsWithBufferEncoding extends OneShotDigestOptions {
outputEncoding: "buffer";
}
export function hash(
algorithm: string,
data: string | ArrayBufferView,
options?: OneShotDigestOptionsWithStringEncoding | BinaryToTextEncoding,
): string;
export function hash(
algorithm: string,
data: string | ArrayBufferView,
options: OneShotDigestOptionsWithBufferEncoding | "buffer",
): Buffer;
export function hash(
algorithm: string,
data: string | ArrayBufferView,
options: OneShotDigestOptions | BinaryToTextEncoding | "buffer",
): string | Buffer;
export function timingSafeEqual(
a: ArrayBufferView | ArrayBufferLike,
b: ArrayBufferView | ArrayBufferLike,
): boolean;
/* WebCrypto's getRandomValues (also the webcrypto object's): integer
* typed arrays, filled in place and returned. */
type RandomValuesArray =
| Int8Array
| Uint8Array
| Uint8ClampedArray
| Int16Array
| Uint16Array
| Int32Array
| Uint32Array
| BigInt64Array
| BigUint64Array;
export function getRandomValues<T extends RandomValuesArray>(typedArray: T): T;
/* The WebCrypto global's object and its SubtleCrypto. */
export const webcrypto: Crypto;
export const subtle: SubtleCrypto;
export function randomFillSync<T extends ArrayBufferView | ArrayBufferLike>(
buffer: T,
offset?: number,
size?: number,
): T;
export function randomFill<T extends ArrayBufferView | ArrayBufferLike>(
buffer: T,
callback: (err: Error | null, buf: T) => void,
): void;
export function randomFill<T extends ArrayBufferView | ArrayBufferLike>(
buffer: T,
offset: number,
callback: (err: Error | null, buf: T) => void,
): void;
export function randomFill<T extends ArrayBufferView | ArrayBufferLike>(
buffer: T,
offset: number,
size: number,
callback: (err: Error | null, buf: T) => void,
): void;
export function randomInt(max: number): number;
export function randomInt(min: number, max: number): number;
export function randomInt(
max: number,
callback: (err: Error | null, value: number) => void,
): void;
export function randomInt(
min: number,
max: number,
callback: (err: Error | null, value: number) => void,
): void;
export function pbkdf2Sync(
password: string | Uint8Array,
salt: string | Uint8Array,
iterations: number,
keylen: number,
digest: string,
): Buffer;
export function pbkdf2(
password: string | Uint8Array,
salt: string | Uint8Array,
iterations: number,
keylen: number,
digest: string,
callback: (error: Error | null, derivedKey: Buffer) => void,
): void;
export function randomBytes(
size: number,
callback: (error: Error | null, buffer: Buffer) => void,
): void;
export type BinaryLike = string | ArrayBuffer | ArrayBufferView;
/* Cipheriv/Decipheriv: aes-128/192/256 in cbc, ctr, gcm, ccm, ecb, cfb,
* cfb8, cfb1, and ofb modes and their key wraps, des-ede3 and des-ede,
* chacha20, and chacha20-poly1305. Both are Transforms: written chunks go
* through update(), and the end pushes final(). */
export type CipherCCMTypes = "aes-128-ccm" | "aes-192-ccm" | "aes-256-ccm";
export type CipherGCMTypes = "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm";
export type CipherChaCha20Poly1305Types = "chacha20-poly1305";
export type CipherKey = BinaryLike | KeyObject;
export interface CipherCCMOptions {
authTagLength: number;
}
export interface CipherGCMOptions {
authTagLength?: number;
}
export interface CipherChaCha20Poly1305Options {
authTagLength?: number;
}
export interface Cipheriv extends Transform {
update(data: string | ArrayBufferView): Buffer;
update(data: string, inputEncoding: BufferEncoding): Buffer;
update(data: ArrayBufferView, inputEncoding: undefined, outputEncoding: BufferEncoding): string;
update(
data: string,
inputEncoding: BufferEncoding | undefined,
outputEncoding: BufferEncoding,
): string;
final(): Buffer;
final(outputEncoding: BufferEncoding): string;
setAutoPadding(autoPadding?: boolean): this;
}
export interface CipherCCM extends Cipheriv {
setAAD(buffer: ArrayBufferView, options: { plaintextLength: number }): this;
getAuthTag(): Buffer;
}
export interface CipherGCM extends Cipheriv {
setAAD(buffer: ArrayBufferView, options?: { plaintextLength: number }): this;
getAuthTag(): Buffer;
}
export interface CipherChaCha20Poly1305 extends Cipheriv {
setAAD(buffer: ArrayBufferView, options?: { plaintextLength: number }): this;
getAuthTag(): Buffer;
}
export interface Decipheriv extends Transform {
update(data: ArrayBufferView): Buffer;
update(data: string, inputEncoding: BufferEncoding): Buffer;
update(data: ArrayBufferView, inputEncoding: undefined, outputEncoding: BufferEncoding): string;
update(
data: string,
inputEncoding: BufferEncoding | undefined,
outputEncoding: BufferEncoding,
): string;
final(): Buffer;
final(outputEncoding: BufferEncoding): string;
setAutoPadding(autoPadding?: boolean): this;
}
export interface DecipherCCM extends Decipheriv {
setAuthTag(buffer: ArrayBufferView): this;
setAAD(buffer: ArrayBufferView, options: { plaintextLength: number }): this;
}
export interface DecipherGCM extends Decipheriv {
setAuthTag(buffer: ArrayBufferView): this;
setAAD(buffer: ArrayBufferView, options?: { plaintextLength: number }): this;
}
export interface DecipherChaCha20Poly1305 extends Decipheriv {
setAuthTag(buffer: ArrayBufferView): this;
setAAD(buffer: ArrayBufferView, options?: { plaintextLength: number }): this;
}
export function createCipheriv(
algorithm: CipherCCMTypes,
key: CipherKey,
iv: BinaryLike,
options: CipherCCMOptions,
): CipherCCM;
export function createCipheriv(
algorithm: CipherGCMTypes,
key: CipherKey,
iv: BinaryLike,
options?: CipherGCMOptions,
): CipherGCM;
export function createCipheriv(
algorithm: CipherChaCha20Poly1305Types,
key: CipherKey,
iv: BinaryLike,
options?: CipherChaCha20Poly1305Options,
): CipherChaCha20Poly1305;
export function createCipheriv(
algorithm: string,
key: CipherKey,
iv: BinaryLike | null,
options?: { authTagLength?: number },
): Cipheriv;
export function createDecipheriv(
algorithm: CipherCCMTypes,
key: CipherKey,
iv: BinaryLike,
options: CipherCCMOptions,
): DecipherCCM;
export function createDecipheriv(
algorithm: CipherGCMTypes,
key: CipherKey,
iv: BinaryLike,
options?: CipherGCMOptions,
): DecipherGCM;
export function createDecipheriv(
algorithm: CipherChaCha20Poly1305Types,
key: CipherKey,
iv: BinaryLike,
options?: CipherChaCha20Poly1305Options,
): DecipherChaCha20Poly1305;
export function createDecipheriv(
algorithm: string,
key: CipherKey,
iv: BinaryLike | null,
options?: { authTagLength?: number },
): Decipheriv;
export type ECDHKeyFormat = "compressed" | "uncompressed" | "hybrid";
export class ECDH {
private constructor();
static convertKey(
key: BinaryLike,
curve: string,
inputEncoding?: BinaryToTextEncoding,
outputEncoding?: "latin1" | "hex" | "base64" | "base64url",
format?: ECDHKeyFormat,
): Buffer | string;
generateKeys(): Buffer;
generateKeys(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string;
computeSecret(otherPublicKey: ArrayBufferView): Buffer;
computeSecret(otherPublicKey: string, inputEncoding: BinaryToTextEncoding): Buffer;
computeSecret(otherPublicKey: ArrayBufferView, outputEncoding: BinaryToTextEncoding): string;
computeSecret(
otherPublicKey: string,
inputEncoding: BinaryToTextEncoding,
outputEncoding: BinaryToTextEncoding,
): string;
getPrivateKey(): Buffer;
getPrivateKey(encoding: BinaryToTextEncoding): string;
getPublicKey(encoding?: null, format?: ECDHKeyFormat): Buffer;
getPublicKey(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string;
setPrivateKey(privateKey: ArrayBufferView): void;
setPrivateKey(privateKey: string, encoding: BinaryToTextEncoding): void;
}
export function createECDH(curveName: string): ECDH;
export class DiffieHellman {
private constructor();
generateKeys(): Buffer;
generateKeys(encoding: BinaryToTextEncoding): string;
computeSecret(
otherPublicKey: ArrayBufferView,
inputEncoding?: null,
outputEncoding?: null,
): Buffer;
computeSecret(
otherPublicKey: string,
inputEncoding: BinaryToTextEncoding,
outputEncoding?: null,
): Buffer;
computeSecret(
otherPublicKey: ArrayBufferView,
inputEncoding: null,
outputEncoding: BinaryToTextEncoding,
): string;
computeSecret(
otherPublicKey: string,
inputEncoding: BinaryToTextEncoding,
outputEncoding: BinaryToTextEncoding,
): string;
getPrime(): Buffer;
getPrime(encoding: BinaryToTextEncoding): string;
getGenerator(): Buffer;
getGenerator(encoding: BinaryToTextEncoding): string;
getPublicKey(): Buffer;
getPublicKey(encoding: BinaryToTextEncoding): string;
getPrivateKey(): Buffer;
getPrivateKey(encoding: BinaryToTextEncoding): string;
setPublicKey(publicKey: ArrayBufferView): void;
setPublicKey(publicKey: string, encoding: BufferEncoding): void;
setPrivateKey(privateKey: ArrayBufferView): void;
setPrivateKey(privateKey: string, encoding: BufferEncoding): void;
verifyError: number;
}
export type DiffieHellmanGroup = Omit<DiffieHellman, "setPublicKey" | "setPrivateKey">;
export function createDiffieHellman(primeLength: number, generator?: number): DiffieHellman;
export function createDiffieHellman(
prime: ArrayBuffer | ArrayBufferView,
generator?: number | ArrayBuffer | ArrayBufferView,
): DiffieHellman;
export function createDiffieHellman(
prime: ArrayBuffer | ArrayBufferView,
generator: string,
generatorEncoding: BinaryToTextEncoding,
): DiffieHellman;
export function createDiffieHellman(
prime: string,
primeEncoding: BinaryToTextEncoding,
generator?: number | ArrayBuffer | ArrayBufferView,
): DiffieHellman;
export function createDiffieHellman(
prime: string,
primeEncoding: BinaryToTextEncoding,
generator: string,
generatorEncoding: BinaryToTextEncoding,
): DiffieHellman;
export function getDiffieHellman(groupName: string): DiffieHellmanGroup;
export function createDiffieHellmanGroup(name: string): DiffieHellmanGroup;
export type LargeNumberLike = ArrayBufferView | SharedArrayBuffer | ArrayBuffer | bigint;
export interface GeneratePrimeOptions {
add?: LargeNumberLike | undefined;
rem?: LargeNumberLike | undefined;
safe?: boolean | undefined;
bigint?: boolean | undefined;
}
export interface GeneratePrimeOptionsBigInt extends GeneratePrimeOptions {
bigint: true;
}
export interface GeneratePrimeOptionsArrayBuffer extends GeneratePrimeOptions {
bigint?: false | undefined;
}
export function generatePrime(
size: number,
callback: (err: Error | null, prime: ArrayBuffer) => void,
): void;
export function generatePrime(
size: number,
options: GeneratePrimeOptionsBigInt,
callback: (err: Error | null, prime: bigint) => void,
): void;
export function generatePrime(
size: number,
options: GeneratePrimeOptionsArrayBuffer,
callback: (err: Error | null, prime: ArrayBuffer) => void,
): void;
export function generatePrime(
size: number,
options: GeneratePrimeOptions,
callback: (err: Error | null, prime: ArrayBuffer | bigint) => void,
): void;
export function generatePrimeSync(size: number): ArrayBuffer;
export function generatePrimeSync(size: number, options: GeneratePrimeOptionsBigInt): bigint;
export function generatePrimeSync(
size: number,
options: GeneratePrimeOptionsArrayBuffer,
): ArrayBuffer;
export function generatePrimeSync(
size: number,
options: GeneratePrimeOptions,
): ArrayBuffer | bigint;
export interface CheckPrimeOptions {
checks?: number | undefined;
}
export function checkPrime(
value: LargeNumberLike,
callback: (err: Error | null, result: boolean) => void,
): void;
export function checkPrime(
value: LargeNumberLike,
options: CheckPrimeOptions,
callback: (err: Error | null, result: boolean) => void,
): void;
export function checkPrimeSync(candidate: LargeNumberLike, options?: CheckPrimeOptions): boolean;
export interface ScryptOptions {
N?: number;
r?: number;
p?: number;
cost?: number;
blockSize?: number;
parallelization?: number;
maxmem?: number;
}
export function scryptSync(
password: BinaryLike,
salt: BinaryLike,
keylen: number,
options?: ScryptOptions,
): Buffer;
export function scrypt(
password: BinaryLike,
salt: BinaryLike,
keylen: number,
callback: (error: Error | null, derivedKey: Buffer) => void,
): void;
export function scrypt(
password: BinaryLike,
salt: BinaryLike,
keylen: number,
options: ScryptOptions,
callback: (error: Error | null, derivedKey: Buffer) => void,
): void;
export function hkdfSync(
digest: string,
ikm: BinaryLike | KeyObject,
salt: BinaryLike,
info: BinaryLike,
keylen: number,
): ArrayBuffer;
export function hkdf(
digest: string,
ikm: BinaryLike | KeyObject,
salt: BinaryLike,
info: BinaryLike,
keylen: number,
callback: (error: Error | null, derivedKey: ArrayBuffer) => void,
): void;
/* The lowered X509Certificate surface is the data-record slice: the
* fields below, all computed at construction (raw decodes the input,
* and the others read raw). validFrom/validTo are Node's
* ASN1_TIME_print strings ("Jul 1 00:00:00 2026 GMT"). Unparseable
* input throws Node's ERR_OSSL_PEM_NO_START_LINE Error. */
export class X509Certificate {
constructor(buffer: Uint8Array | string);
readonly ca: boolean;
readonly fingerprint: string;
readonly fingerprint256: string;
readonly fingerprint512: string;
readonly subject: string;
readonly subjectAltName: string | undefined;
readonly infoAccess: string | undefined;
readonly issuer: string;
readonly raw: Buffer;
readonly serialNumber: string;
readonly signatureAlgorithm: string | undefined;
readonly signatureAlgorithmOid: string;
readonly validFrom: string;
readonly validFromDate: Date;
readonly validTo: string;
readonly validToDate: Date;
/* the certificate's public key; every read answers the same KeyObject */
readonly publicKey: KeyObject;
verify(publicKey: KeyObject): boolean;
checkPrivateKey(privateKey: KeyObject): boolean;
checkIssued(otherCert: X509Certificate): boolean;
checkHost(name: string, options?: X509CheckOptions): string | undefined;
checkEmail(email: string, options?: X509CheckOptions): string | undefined;
checkIP(ip: string): string | undefined;
toLegacyObject(): import("tls").PeerCertificate;
}
export interface X509CheckOptions {
subject?: "always" | "default" | "never";
wildcards?: boolean;
partialWildcards?: boolean;
multiLabelWildcards?: boolean;
singleLabelSubdomains?: boolean;
}
/* The crypto introspection statics: getFips() answers 0 (a compiled
* binary is never a FIPS build), the three name lists bake as fresh
* string[] literals of Node v24 answers, and constants (below) bakes
* per member like http2.constants. */
export function getFips(): 1 | 0;
export function getCiphers(): string[];
export type CipherMode =
| "cbc"
| "ccm"
| "cfb"
| "ctr"
| "ecb"
| "gcm"
| "ocb"
| "ofb"
| "stream"
| "wrap"
| "xts";
export interface CipherInfoOptions {
keyLength?: number | undefined;
ivLength?: number | undefined;
}
export interface CipherInfo {
name: string;
nid: number;
blockSize?: number | undefined;
ivLength?: number | undefined;
keyLength: number;
mode: CipherMode;
}
export function getCipherInfo(
nameOrNid: string | number,
options?: CipherInfoOptions,
): CipherInfo | undefined;
export function getHashes(): string[];
export function getCurves(): string[];
/* Node v24 crypto.constants, literal-typed (the Http2Constants
* stance). Every ACCESS bakes as its literal at lowering; the object
* itself never materializes (bare crypto.constants value uses fence). */
export interface CryptoConstants {
readonly OPENSSL_VERSION_NUMBER: 810549376;
readonly SSL_OP_ALL: 2147485776;
readonly SSL_OP_ALLOW_NO_DHE_KEX: 1024;
readonly SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: 262144;
readonly SSL_OP_CIPHER_SERVER_PREFERENCE: 4194304;
readonly SSL_OP_CISCO_ANYCONNECT: 32768;
readonly SSL_OP_COOKIE_EXCHANGE: 8192;
readonly SSL_OP_CRYPTOPRO_TLSEXT_BUG: 2147483648;
readonly SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: 2048;
readonly SSL_OP_LEGACY_SERVER_CONNECT: 4;
readonly SSL_OP_NO_COMPRESSION: 131072;
readonly SSL_OP_NO_ENCRYPT_THEN_MAC: 524288;
readonly SSL_OP_NO_QUERY_MTU: 4096;
readonly SSL_OP_NO_RENEGOTIATION: 1073741824;
readonly SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: 65536;
readonly SSL_OP_NO_SSLv2: 0;
readonly SSL_OP_NO_SSLv3: 33554432;
readonly SSL_OP_NO_TICKET: 16384;
readonly SSL_OP_NO_TLSv1: 67108864;
readonly SSL_OP_NO_TLSv1_1: 268435456;
readonly SSL_OP_NO_TLSv1_2: 134217728;
readonly SSL_OP_NO_TLSv1_3: 536870912;
readonly SSL_OP_PRIORITIZE_CHACHA: 2097152;
readonly SSL_OP_TLS_ROLLBACK_BUG: 8388608;
readonly ENGINE_METHOD_RSA: 1;
readonly ENGINE_METHOD_DSA: 2;
readonly ENGINE_METHOD_DH: 4;
readonly ENGINE_METHOD_RAND: 8;
readonly ENGINE_METHOD_EC: 2048;
readonly ENGINE_METHOD_CIPHERS: 64;
readonly ENGINE_METHOD_DIGESTS: 128;
readonly ENGINE_METHOD_PKEY_METHS: 512;
readonly ENGINE_METHOD_PKEY_ASN1_METHS: 1024;
readonly ENGINE_METHOD_ALL: 65535;
readonly ENGINE_METHOD_NONE: 0;
readonly DH_CHECK_P_NOT_SAFE_PRIME: 2;
readonly DH_CHECK_P_NOT_PRIME: 1;
readonly DH_UNABLE_TO_CHECK_GENERATOR: 4;
readonly DH_NOT_SUITABLE_GENERATOR: 8;
readonly RSA_PKCS1_PADDING: 1;
readonly RSA_SSLV23_PADDING: 2;
readonly RSA_NO_PADDING: 3;
readonly RSA_PKCS1_OAEP_PADDING: 4;
readonly RSA_X931_PADDING: 5;
readonly RSA_PKCS1_PSS_PADDING: 6;
readonly RSA_PSS_SALTLEN_DIGEST: -1;
readonly RSA_PSS_SALTLEN_MAX_SIGN: -2;
readonly RSA_PSS_SALTLEN_AUTO: -2;
readonly defaultCoreCipherList: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA";
readonly TLS1_VERSION: 769;
readonly TLS1_1_VERSION: 770;
readonly TLS1_2_VERSION: 771;
readonly TLS1_3_VERSION: 772;
readonly POINT_CONVERSION_COMPRESSED: 2;
readonly POINT_CONVERSION_UNCOMPRESSED: 4;
readonly POINT_CONVERSION_HYBRID: 6;
readonly defaultCipherList: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA";
}
export const constants: CryptoConstants;
}
declare module "node:crypto" {
export * from "crypto";
}
+58
View File
@@ -0,0 +1,58 @@
/* node:dgram — UDP sockets over the event loop (scr_dgram.c, linked only
* into using binaries). createSocket takes "udp4" or the
* { type: "udp4", reuseAddr? } literal; bind/connect bind NOW and defer
* 'listening'/'connect' to the next loop turn; send takes one string or
* Buffer datagram with an explicit port + address (the connected-send
* and callback forms have no lowering); address() returns the real
* {address, family, port} record and THROWS "Not running" before bind,
* like Node. The socket options throw Node's errors (EBADF before bind);
* add/dropMembership before bind is refused at run time (SC2020). 'error'
* with no listener exits 1 (the unhandled EventEmitter 'error' behavior). */
declare module "dgram" {
export interface AddressInfo {
address: string;
family: string;
port: number;
}
export interface RemoteInfo {
address: string;
family: string;
port: number;
size: number;
}
export interface Socket {
bind(port: number, address?: string, callback?: () => void): void;
connect(port: number, address?: string, callback?: () => void): void;
send(msg: string | Uint8Array, port: number, address: string): void;
address(): AddressInfo;
close(callback?: () => void): void;
disconnect(): void;
unref(): void;
ref(): void;
setBroadcast(flag: boolean): void;
setTTL(ttl: number): number;
setMulticastTTL(ttl: number): number;
setMulticastLoopback(flag: boolean): boolean;
setMulticastInterface(multicastInterface: string): void;
addMembership(multicastAddress: string, multicastInterface?: string): void;
dropMembership(multicastAddress: string, multicastInterface?: string): void;
getRecvBufferSize(): number;
getSendBufferSize(): number;
setRecvBufferSize(size: number): void;
setSendBufferSize(size: number): void;
getSendQueueSize(): number;
getSendQueueCount(): number;
on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): void;
on(event: "listening" | "close" | "connect", listener: () => void): void;
on(event: "error", listener: (err: Error) => void): void;
once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): void;
once(event: "listening" | "close" | "connect", listener: () => void): void;
once(event: "error", listener: (err: Error) => void): void;
}
export function createSocket(type: "udp4"): Socket;
export function createSocket(options: { type: "udp4"; reuseAddr?: boolean }): Socket;
}
declare module "node:dgram" {
export * from "dgram";
}
@@ -0,0 +1,87 @@
/// <reference path="./async_hooks.d.ts" />
/* node:diagnostics_channel — the in-process pub/sub core: named channels,
* subscribe/unsubscribe (module-level and channel-level), publish with any
* dyn-convertible message. Channel values are f64 handles into the
* runtime's channel registry (the readline.Interface precedent — channels
* are process-lived in Node too, its WeakRef machinery aside).
* The store-binding surface (bindStore/unbindStore/runStores) lowers onto
* the AsyncLocalStorage integration (dc.chan* libCalls).
*
* TracingChannel (tracingChannel) is the five-event-channel collection:
* an f64 handle into the runtime's tracing registry (type-mapper.ts maps the
* name like Channel). subscribe/unsubscribe walk a handlers object;
* traceSync/traceCallback run Node's publish choreography in the runtime
* (context defaults to a fresh {}); tracePromise is declared (the member
* exists in Node) but fences at the call site — the traced function's
* promise cannot cross the checked-dynamic tree boundary yet. */
declare module "node:diagnostics_channel" {
export type ChannelListener = (message: unknown, name: string) => void;
export interface Channel {
readonly name: string;
readonly hasSubscribers: boolean;
publish(message: unknown): void;
subscribe(onMessage: ChannelListener): void;
unsubscribe(onMessage: ChannelListener): boolean;
bindStore(
store: import("async_hooks").AsyncLocalStorage<any>,
transform?: (context: any) => any,
): void;
unbindStore(store: import("async_hooks").AsyncLocalStorage<any>): boolean;
runStores(context: unknown, fn: (...args: any[]) => any, thisArg?: any, ...args: any[]): any;
}
export function channel(name: string): Channel;
export function subscribe(name: string, onMessage: ChannelListener): void;
export function unsubscribe(name: string, onMessage: ChannelListener): boolean;
export function hasSubscribers(name: string): boolean;
export interface TracingChannelSubscribers {
start?: (message: any) => void;
end?: (message: any) => void;
asyncStart?: (message: any) => void;
asyncEnd?: (message: any) => void;
error?: (message: any) => void;
}
export interface TracingChannelCollection {
start: Channel;
end: Channel;
asyncStart: Channel;
asyncEnd: Channel;
error: Channel;
}
export interface TracingChannel {
start: Channel;
end: Channel;
asyncStart: Channel;
asyncEnd: Channel;
error: Channel;
readonly hasSubscribers: boolean;
subscribe(subscribers: TracingChannelSubscribers): void;
/** True when every present handler was found and removed (Node's
* all-found conjunction; @types/node under-declares this as void). */
unsubscribe(subscribers: TracingChannelSubscribers): boolean;
traceSync<ThisArg = any, Args extends any[] = any[], Result = any>(
fn: (this: ThisArg, ...args: Args) => Result,
context?: object,
thisArg?: ThisArg,
...args: Args
): Result;
tracePromise<ThisArg = any, Args extends any[] = any[], Result = any>(
fn: (this: ThisArg, ...args: Args) => Promise<Result>,
context?: object,
thisArg?: ThisArg,
...args: Args
): Promise<Result>;
traceCallback<ThisArg = any, Args extends any[] = any[], Result = any>(
fn: (this: ThisArg, ...args: Args) => Result,
position?: number,
context?: object,
thisArg?: ThisArg,
...args: Args
): Result;
}
export function tracingChannel(nameOrChannels: string | TracingChannelCollection): TracingChannel;
}
declare module "diagnostics_channel" {
export * from "node:diagnostics_channel";
}
@@ -0,0 +1,27 @@
/// <reference path="./dns.d.ts" />
/* node:dns/promises — lookup and lookupService as promises over the same
* resolution as the callback forms: argument errors throw synchronously,
* failures reject with the callbacks' errors. */
declare module "dns/promises" {
import type { LookupAddress, LookupAllOptions, LookupOneOptions, LookupOptions } from "dns";
export function lookup(hostname: string, family: number): Promise<LookupAddress>;
export function lookup(hostname: string, options: LookupOneOptions): Promise<LookupAddress>;
export function lookup(hostname: string, options: LookupAllOptions): Promise<LookupAddress[]>;
export function lookup(
hostname: string,
options: LookupOptions,
): Promise<LookupAddress | LookupAddress[]>;
export function lookup(hostname: string): Promise<LookupAddress>;
export function lookupService(
address: string,
port: number,
): Promise<{ hostname: string; service: string }>;
export function getServers(): string[];
export function getDefaultResultOrder(): "ipv4first" | "ipv6first" | "verbatim";
export function setDefaultResultOrder(order: "ipv4first" | "ipv6first" | "verbatim"): void;
}
declare module "node:dns/promises" {
export * from "dns/promises";
}
+65
View File
@@ -0,0 +1,65 @@
/// <reference path="./dns-promises.d.ts" />
/* node:dns — the lookup slice (scr_dgram.c hosts it; getaddrinfo runs AT
* CALL TIME and the callback defers to the next loop turn — SEMANTICS.md
* documents the blocking divergence). Only the { family: 4 } options
* form lowers; failures deliver Node's error shape ("getaddrinfo
* ENOTFOUND <hostname>") as the callback's Error argument, with "" for
* the address where Node passes undefined. */
declare module "dns" {
export interface LookupAddress {
address: string;
family: number;
}
export interface LookupOptions {
family?: number | "IPv4" | "IPv6";
hints?: number;
all?: boolean;
order?: "ipv4first" | "ipv6first" | "verbatim";
verbatim?: boolean;
}
export interface LookupOneOptions extends LookupOptions {
all?: false;
}
export interface LookupAllOptions extends LookupOptions {
all: true;
}
/* The callback comes with the other lookup deliveries (literal
* addresses on the next tick); the options follow lib/dns.js. */
export function lookup(
hostname: string,
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
): void;
export function lookup(
hostname: string,
family: number,
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
): void;
export function lookup(
hostname: string,
options: LookupOneOptions,
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
): void;
export function lookup(
hostname: string,
options: LookupAllOptions,
callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void,
): void;
/* getnameinfo with NI_NAMEREQD: the host's name and the port's service
* name (the number when it has none). */
export function lookupService(
address: string,
port: number,
callback: (err: NodeJS.ErrnoException | null, hostname: string, service: string) => void,
): void;
/* The nameservers /etc/resolv.conf lists. */
export function getServers(): string[];
export function getDefaultResultOrder(): "ipv4first" | "ipv6first" | "verbatim";
export function setDefaultResultOrder(order: "ipv4first" | "ipv6first" | "verbatim"): void;
/* The promise forms (node:dns/promises). */
export const promises: typeof import("dns/promises");
}
declare module "node:dns" {
export * from "dns";
}
+60
View File
@@ -0,0 +1,60 @@
/* node:events — the EventEmitter class (the module object IS the class,
* like Node's `module.exports = EventEmitter`). Listener/emit signatures
* mirror @types/node's untyped `...args: any[]` surface; the compiler's
* lowering unifies each event name's argument tuple program-wide and
* checks annotated listener parameters against it (unannotated non-empty
* parameter lists have no static types and fence at the registration). */
declare module "events" {
class EventEmitter {
constructor();
static defaultMaxListeners: number;
/* Listeners registered under this symbol observe 'error' emits first
* (an emit with no 'error' listener still throws). */
static readonly errorMonitor: unique symbol;
static addAbortListener(signal: AbortSignal, listener: (event: Event) => void): Disposable;
on(eventName: string | symbol, listener: (...args: any[]) => void): this;
addListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
once(eventName: string | symbol, listener: (...args: any[]) => void): this;
prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
off(eventName: string | symbol, listener: (...args: any[]) => void): this;
removeListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
removeAllListeners(eventName?: string | symbol): this;
emit(eventName: string | symbol, ...args: any[]): boolean;
listenerCount(eventName: string | symbol, listener?: (...args: any[]) => void): number;
/* Declared as zero-parameter closures so the RESULT is statically
* consumable (.length, indexing, identity): the lowering only admits
* these calls for events whose argument tuple is empty — a listener
* pulled from the array is then safely callable too. Events with
* arguments fence (their element type would lie). */
listeners(eventName: string): Array<() => void>;
rawListeners(eventName: string): Array<() => void>;
eventNames(): string[];
setMaxListeners(n: number): this;
getMaxListeners(): number;
}
import internal = require("node:events");
namespace EventEmitter {
// The class under its own name, so `import { EventEmitter }` resolves
// (the @types/node namespace-alias pattern).
export { internal as EventEmitter };
// The event's arguments, as checked-dynamic values.
export function once(
emitter: EventEmitter | NodeJS.ReadableStream | NodeJS.WritableStream,
eventName: string,
options?: { signal?: AbortSignal },
): Promise<unknown[]>;
/* The emitter's own listenerCount/getMaxListeners/setMaxListeners/
* listeners, over EventEmitter instances. */
export function listenerCount(emitter: EventEmitter, eventName: string | symbol): number;
export function getMaxListeners(emitter: EventEmitter): number;
export function setMaxListeners(n?: number, ...eventTargets: EventEmitter[]): void;
export function getEventListeners(emitter: EventEmitter, name: string): Array<() => void>;
}
export = EventEmitter;
}
declare module "node:events" {
import events = require("events");
export = events;
}
+225
View File
@@ -0,0 +1,225 @@
/// <reference path="./fs.d.ts" />
/* fs/promises — the SAME synchronous operations behind already-settled
* promises: success fulfills, failure REJECTS with the would-be thrown
* error (catchable at the await, like Node). DOCUMENTED DIVERGENCE
* (SEMANTICS.md): the syscall blocks the event loop, so I/O never
* interleaves with timers or other fibers — observable only in concurrent
* code. readFile is utf8-only, like readFileSync. */
declare module "fs/promises" {
export interface FileReadResult<T extends Uint8Array> {
bytesRead: number;
buffer: T;
}
export interface FileWriteResult<T> {
bytesWritten: number;
buffer: T;
}
export interface FileReadvResult<T extends Uint8Array[]> {
bytesRead: number;
buffers: T;
}
export interface FileWritevResult<T extends Uint8Array[]> {
bytesWritten: number;
buffers: T;
}
export interface FileReadOptions<T extends Uint8Array = Buffer> {
buffer?: T;
offset?: number | null;
length?: number | null;
position?: number | null;
}
/* The streams over a FileHandle (createReadStream, createWriteStream,
* readLines): fs streams that hold the handle until they close; closing
* the stream closes the handle unless autoClose is false. */
export interface CreateReadStreamOptions {
encoding?: BufferEncoding | null;
autoClose?: boolean;
emitClose?: boolean;
start?: number;
end?: number;
highWaterMark?: number;
}
export interface CreateWriteStreamOptions {
encoding?: BufferEncoding | null;
autoClose?: boolean;
emitClose?: boolean;
start?: number;
highWaterMark?: number;
flush?: boolean;
}
export interface FileHandle extends AsyncDisposable {
readonly fd: number;
close(): Promise<void>;
createReadStream(options?: CreateReadStreamOptions): import("node:fs").ReadStream;
createWriteStream(options?: CreateWriteStreamOptions): import("node:fs").WriteStream;
readLines(options?: CreateReadStreamOptions): import("node:readline").Interface;
sync(): Promise<void>;
datasync(): Promise<void>;
truncate(len?: number): Promise<void>;
chmod(mode: number): Promise<void>;
utimes(atime: number | string | Date, mtime: number | string | Date): Promise<void>;
readv<T extends Uint8Array[]>(
buffers: T,
position?: number | null,
): Promise<FileReadvResult<T>>;
writev<T extends Uint8Array[]>(
buffers: T,
position?: number | null,
): Promise<FileWritevResult<T>>;
read<T extends Uint8Array = Buffer>(
options?: FileReadOptions<T> | null,
): Promise<FileReadResult<T>>;
read<T extends Uint8Array>(
buffer: T,
options: Omit<FileReadOptions<T>, "buffer">,
): Promise<FileReadResult<T>>;
read<T extends Uint8Array>(
buffer: T,
offset?: number | null,
length?: number | null,
position?: number | null,
): Promise<FileReadResult<T>>;
write<T extends Uint8Array>(
buffer: T,
offset?: number | null,
length?: number | null,
position?: number | null,
): Promise<FileWriteResult<T>>;
write<T extends Uint8Array>(
buffer: T,
options: Omit<FileReadOptions<T>, "buffer">,
): Promise<FileWriteResult<T>>;
write(
data: string,
position?: number | null,
encoding?: "utf8" | "utf-8" | null,
): Promise<FileWriteResult<string>>;
readFile(options?: null): Promise<Buffer>;
readFile(encoding: "utf8" | "utf-8"): Promise<string>;
writeFile(data: string | Uint8Array, encoding?: "utf8" | "utf-8" | null): Promise<void>;
appendFile(data: string | Uint8Array, encoding?: "utf8" | "utf-8" | null): Promise<void>;
stat(): Promise<import("node:fs").Stats>;
[Symbol.asyncDispose](): Promise<void>;
}
export function open(path: string | URL, flags?: string, mode?: number): Promise<FileHandle>;
export function link(
existingPath: string | Uint8Array | URL,
newPath: string | Uint8Array | URL,
): Promise<void>;
export function symlink(
target: string | Uint8Array | URL,
path: string | Uint8Array | URL,
type?: string | null,
): Promise<void>;
export function cp(
source: string | URL,
destination: string | URL,
options?: import("node:fs").CopyOptions,
): Promise<void>;
export function readlink(
path: string | Uint8Array | URL,
options: "buffer" | { encoding: "buffer" },
): Promise<Buffer>;
export function readlink(
path: string | Uint8Array | URL,
options?: BufferEncoding | { encoding?: BufferEncoding | null } | null,
): Promise<string>;
export function readlink(
path: string | Uint8Array | URL,
options: string | { encoding?: string | null } | null,
): Promise<string | Buffer>;
export function utimes(
path: string | Uint8Array | URL,
atime: number | string | Date,
mtime: number | string | Date,
): Promise<void>;
export function lutimes(
path: string | Uint8Array | URL,
atime: number | string | Date,
mtime: number | string | Date,
): Promise<void>;
export function readFile(path: string | URL, encoding: "utf8" | "utf-8"): Promise<string>;
export function readFile(
path: string | URL,
options: BufferEncoding | { encoding: BufferEncoding },
): Promise<string>;
export function readFile(path: string | URL): Promise<Buffer>;
export function writeFile(
path: string | URL,
data: string,
options?: {
mode?: number;
encoding?: "utf8" | "utf-8";
flag?: string;
[option: string]: unknown;
},
): Promise<void>;
export function writeFile(
path: string | URL,
data: string,
encoding: "utf8" | "utf-8",
): Promise<void>;
export function mkdir(
path: string | URL,
options?: { recursive?: boolean; mode?: number },
): Promise<void>;
export function readdir(path: string | URL): Promise<string[]>;
export function readdir(
path: string | URL,
options: {
encoding?: "utf8" | "utf-8";
withFileTypes: true;
recursive?: boolean;
[option: string]: unknown;
},
): Promise<import("node:fs").Dirent[]>;
/* The async iterator form of fs.globSync: iterate it with for await. */
export function glob(
pattern: string | readonly string[],
options?: import("node:fs").GlobOptions,
): AsyncIterableIterator<string>;
export function glob(
pattern: string | readonly string[],
options: import("node:fs").GlobOptionsWithFileTypes,
): AsyncIterableIterator<import("node:fs").Dirent>;
export function rm(path: string | URL): Promise<void>;
export function rm(
path: string | URL,
options: { recursive?: boolean; force?: boolean; maxRetries?: number; retryDelay?: number },
): Promise<void>;
export function stat(path: string | URL): Promise<import("node:fs").Stats>;
export function statfs(
path: string | Uint8Array | URL,
options?: import("node:fs").StatFsOptions & { bigint?: false },
): Promise<import("node:fs").StatsFs>;
export function statfs(
path: string | Uint8Array | URL,
options: import("node:fs").StatFsOptions & { bigint: true },
): Promise<import("node:fs").BigIntStatsFs>;
export function statfs(
path: string | Uint8Array | URL,
options?: import("node:fs").StatFsOptions,
): Promise<import("node:fs").StatsFs | import("node:fs").BigIntStatsFs>;
export function realpath(path: string | URL): Promise<string>;
export function lstat(path: string | URL): Promise<import("node:fs").Stats>;
export function unlink(path: string | URL): Promise<void>;
export function chmod(path: string | URL, mode: number): Promise<void>;
export function chown(path: string | URL, uid: number, gid: number): Promise<void>;
export function lchown(path: string | URL, uid: number, gid: number): Promise<void>;
export function access(path: string | URL, mode?: number): Promise<void>;
export function truncate(path: string | URL, len?: number): Promise<void>;
export function appendFile(path: string | URL, data: string | Uint8Array): Promise<void>;
export function copyFile(src: string | URL, dest: string | URL): Promise<void>;
export function mkdtemp(prefix: string | URL): Promise<string>;
export function rmdir(path: string | URL): Promise<void>;
export function rename(oldPath: string | URL, newPath: string | URL): Promise<void>;
export function opendir(
path: string | URL,
options?: import("node:fs").OpenDirOptions,
): Promise<import("node:fs").Dir>;
}
declare module "node:fs/promises" {
export * from "fs/promises";
}
+587
View File
@@ -0,0 +1,587 @@
/// <reference path="./fs-promises.d.ts" />
/// <reference path="./stream.d.ts" />
/* The synchronous node:fs surface — utf8-only, no options objects, no
* Buffers. Importing "node:fs" resolves here (preflight allowlists exactly
* the ambient-declared node: modules); every function lowers to a `libCall`
* with a scr_fs_* runtime implementation. Failures throw CATCHABLE string
* values formatted like Node's error messages ("ENOENT: no such file or
* directory, open 'x'"). `rmSync` removes FILES only (like Node without
* `recursive`); empty directories go through `rmdirSync`. */
declare module "node:fs" {
import { Readable, Writable } from "stream";
export function readFileSync(path: string | number | URL, encoding: BufferEncoding): string;
export function readFileSync(
path: string | number | URL,
options: { encoding: BufferEncoding },
): string;
export function readFileSync(path: string | number | URL): Buffer;
export function readFileSync(path: string | URL, options: unknown): string | Buffer;
/* Error-first callbacks select string or Buffer data from their encoding.
* Unknown options retain that union until the caller validates the value. */
export function readFile(
path: string,
options: unknown,
callback: (error: Error | null, data: string | Buffer) => void,
): void;
/* The options form carries the mode (applied at CREATION only, like
* Node — an existing file keeps its permissions) and/or the utf8
* encoding spelling. */
export function writeFileSync(
path: string | URL,
data: string,
/* The options-record stance (see http.RequestOptions): flag fences
* by name at the call site; undocumented keys drop like Node. */
options?: {
mode?: number;
encoding?: "utf8" | "utf-8";
flag?: string;
[option: string]: unknown;
},
): void;
/* The bare-encoding spelling — the options record's encoding key alone. */
export function writeFileSync(path: string | URL, data: string, encoding: "utf8" | "utf-8"): void;
export function writeFileSync(path: string | URL, data: string | Uint8Array): void;
export function appendFileSync(path: string | URL, data: string | Uint8Array): void;
export function existsSync(path: string | URL): boolean;
export function mkdirSync(path: string | URL): void;
export function mkdirSync(
path: string | URL,
options: { recursive?: boolean; mode?: number },
): void;
export function unlinkSync(path: string | URL): void;
export function chmodSync(path: string | URL, mode: number): void;
export function fchmodSync(fd: number, mode: number): void;
export function fsyncSync(fd: number): void;
export function linkSync(
existingPath: string | Uint8Array | URL,
newPath: string | Uint8Array | URL,
): void;
export function symlinkSync(
target: string | Uint8Array | URL,
path: string | Uint8Array | URL,
type?: string | null,
): void;
/* fs.cpSync / fs.cp: copies a file, symlink or (with recursive) a
* directory tree. filter decides per path; the callback and promise
* forms complete the copy before reporting. */
export interface CopySyncOptions {
dereference?: boolean;
errorOnExist?: boolean;
filter?: (source: string, destination: string) => boolean;
force?: boolean;
mode?: number;
preserveTimestamps?: boolean;
recursive?: boolean;
verbatimSymlinks?: boolean;
}
export interface CopyOptions {
dereference?: boolean;
errorOnExist?: boolean;
filter?: (source: string, destination: string) => boolean | Promise<boolean>;
force?: boolean;
mode?: number;
preserveTimestamps?: boolean;
recursive?: boolean;
verbatimSymlinks?: boolean;
}
export function cpSync(
source: string | URL,
destination: string | URL,
options?: CopySyncOptions,
): void;
export function cp(
source: string | URL,
destination: string | URL,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function cp(
source: string | URL,
destination: string | URL,
options: CopyOptions,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function symlink(
target: string | Uint8Array | URL,
path: string | Uint8Array | URL,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function symlink(
target: string | Uint8Array | URL,
path: string | Uint8Array | URL,
type: string | null | undefined,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function link(
existingPath: string | Uint8Array | URL,
newPath: string | Uint8Array | URL,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function readlink(
path: string | Uint8Array | URL,
callback: (err: NodeJS.ErrnoException | null, target: string) => void,
): void;
export function readlink(
path: string | Uint8Array | URL,
options: "buffer" | { encoding: "buffer" },
callback: (err: NodeJS.ErrnoException | null, target: Buffer) => void,
): void;
export function readlink(
path: string | Uint8Array | URL,
options: BufferEncoding | { encoding?: BufferEncoding | null } | null,
callback: (err: NodeJS.ErrnoException | null, target: string) => void,
): void;
export function readlink(
path: string | Uint8Array | URL,
options: string | { encoding?: string | null } | null,
callback: (err: NodeJS.ErrnoException | null, target: string | Buffer) => void,
): void;
export function readlinkSync(
path: string | Uint8Array | URL,
options: "buffer" | { encoding: "buffer" },
): Buffer;
export function readlinkSync(
path: string | Uint8Array | URL,
options?: BufferEncoding | { encoding?: BufferEncoding | null } | null,
): string;
export function readlinkSync(
path: string | Uint8Array | URL,
options: string | { encoding?: string | null } | null,
): string | Buffer;
export function chownSync(path: string | URL, uid: number, gid: number): void;
export function lchownSync(path: string | URL, uid: number, gid: number): void;
export function fchownSync(fd: number, uid: number, gid: number): void;
export function truncateSync(path: string | URL, len?: number): void;
/* The 2-argument form only (Node's mode flags have no lowering). The
* destination is created or truncated carrying the SOURCE's mode. */
export function copyFileSync(src: string | URL, dest: string | URL): void;
export function rename(
oldPath: string,
newPath: string,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function renameSync(oldPath: string | URL, newPath: string | URL): void;
export function rmSync(path: string | URL): void;
/* maxRetries/retryDelay are accepted no-ops (Node retries around
* EBUSY-class races; the synchronous lowering has no re-entrancy that
* needs them). */
export function rmSync(
path: string | URL,
options: { recursive?: boolean; force?: boolean; maxRetries?: number; retryDelay?: number },
): void;
export function rmdirSync(path: string | URL): void;
export function readdirSync(path: string | URL): string[];
/* The recursive form: every entry below the path, relative to it. */
export function readdirSync(
path: string | URL,
options: {
recursive?: boolean;
withFileTypes?: false;
encoding?: "utf8" | "utf-8";
[option: string]: unknown;
},
): string[];
/* The withFileTypes form: Dirent rows (name + parentPath + the type
* probes — the honest subset of Node's Dirent surface). The type is
* interned explicitly in type-mapper.ts (the record's hidden %dtype field
* carries the entry kind; isFile/isDirectory/isSymbolicLink lower as
* reads of it in builtins/process.ts). */
export interface Dirent {
name: string;
parentPath: string;
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
}
export function readdirSync(
path: string | URL,
/* The options-record stance (see http.RequestOptions): recursive
* fences by name at the call site; undocumented keys drop like Node. */
options: { withFileTypes: true; recursive?: boolean; [option: string]: unknown },
): Dirent[];
/* fs.globSync / fs.glob: Node's glob walk over the file system. Patterns
* are minimatch globs (case-insensitive on macOS and Windows); results
* are relative to cwd unless the pattern is absolute. withFileTypes must
* be a literal so the result type is known. */
export interface GlobOptions {
cwd?: string | URL;
exclude?: readonly string[] | ((fileName: string) => boolean);
followSymlinks?: boolean;
withFileTypes?: false;
}
export interface GlobOptionsWithFileTypes {
cwd?: string | URL;
exclude?: readonly string[];
followSymlinks?: boolean;
withFileTypes: true;
}
export function globSync(pattern: string | readonly string[], options?: GlobOptions): string[];
export function globSync(
pattern: string | readonly string[],
options: GlobOptionsWithFileTypes,
): Dirent[];
export function glob(
pattern: string | readonly string[],
callback: (err: NodeJS.ErrnoException | null, matches?: string[]) => void,
): void;
export function glob(
pattern: string | readonly string[],
options: GlobOptions,
callback: (err: NodeJS.ErrnoException | null, matches?: string[]) => void,
): void;
/* fs.Dir: an open directory stream (opendirSync, fs.promises.opendir)
* read one Dirent at a time in OS order; utf8 names, no recursive walk. */
export interface Dir {
readonly path: string;
readSync(): Dirent | null;
read(): Promise<Dirent | null>;
closeSync(): void;
close(): Promise<void>;
[Symbol.asyncIterator](): AsyncIterableIterator<Dirent>;
}
export interface OpenDirOptions {
encoding?: "utf8" | "utf-8";
bufferSize?: number;
}
export function opendirSync(path: string | URL, options?: OpenDirOptions): Dir;
/* fs.ReadStream / fs.WriteStream: runtime Readable and Writable streams
* over a file (scr_fs_stream.c). The options are checked at runtime
* with Node's rules; flags and mode are checked when the file opens, so
* their errors arrive as 'error' events. Instances also emit 'open'
* (with the fd) and 'ready'. */
export interface StreamOptions {
flags?: string;
encoding?: BufferEncoding;
fd?: number;
mode?: number | string;
autoClose?: boolean;
emitClose?: boolean;
start?: number;
highWaterMark?: number;
}
export interface ReadStreamOptions extends StreamOptions {
end?: number;
}
export interface WriteStreamOptions extends StreamOptions {
flush?: boolean;
}
export class ReadStream extends Readable {
readonly bytesRead: number;
readonly path: string | Buffer;
readonly pending: boolean;
close(callback?: () => void): void;
}
export class WriteStream extends Writable {
readonly bytesWritten: number;
readonly path: string | Buffer;
readonly pending: boolean;
close(callback?: () => void): void;
}
export function createReadStream(
path: string | Buffer | URL,
options?: BufferEncoding | ReadStreamOptions,
): ReadStream;
export function createWriteStream(
path: string | Buffer | URL,
options?: BufferEncoding | WriteStreamOptions,
): WriteStream;
export function accessSync(path: string | URL, mode?: number): void;
export function mkdtempSync(prefix: string | URL): string;
export const constants: {
readonly F_OK: number;
readonly R_OK: number;
readonly W_OK: number;
readonly X_OK: number;
readonly O_RDONLY: number;
readonly O_WRONLY: number;
readonly O_RDWR: number;
readonly O_CREAT: number;
readonly O_EXCL: number;
readonly O_NOFOLLOW: number;
readonly O_NONBLOCK: number;
readonly O_TRUNC: number;
readonly O_APPEND: number;
readonly COPYFILE_EXCL: number;
readonly COPYFILE_FICLONE: number;
readonly COPYFILE_FICLONE_FORCE: number;
readonly UV_FS_SYMLINK_DIR: number;
readonly UV_FS_SYMLINK_JUNCTION: number;
readonly UV_DIRENT_UNKNOWN: number;
readonly UV_DIRENT_FILE: number;
readonly UV_DIRENT_DIR: number;
readonly UV_DIRENT_LINK: number;
readonly UV_DIRENT_FIFO: number;
readonly UV_DIRENT_SOCKET: number;
readonly UV_DIRENT_CHAR: number;
readonly UV_DIRENT_BLOCK: number;
readonly UV_FS_O_FILEMAP: number;
readonly UV_FS_O_TEMPORARY: number;
readonly UV_FS_O_SHORT_LIVED: number;
readonly UV_FS_O_SEQUENTIAL: number;
readonly UV_FS_O_RANDOM: number;
readonly UV_FS_COPYFILE_EXCL: number;
readonly UV_FS_COPYFILE_FICLONE: number;
readonly UV_FS_COPYFILE_FICLONE_FORCE: number;
readonly S_IFMT: number;
readonly S_IFREG: number;
readonly S_IFDIR: number;
readonly S_IFCHR: number;
readonly S_IFBLK: number;
readonly S_IFIFO: number;
readonly S_IFLNK: number;
readonly S_IFSOCK: number;
readonly O_NOCTTY: number;
readonly O_DIRECTORY: number;
readonly O_NOATIME: number;
readonly O_SYNC: number;
readonly O_DSYNC: number;
readonly O_SYMLINK: number;
readonly O_DIRECT: number;
readonly S_IRWXU: number;
readonly S_IRUSR: number;
readonly S_IWUSR: number;
readonly S_IXUSR: number;
readonly S_IRWXG: number;
readonly S_IRGRP: number;
readonly S_IWGRP: number;
readonly S_IXGRP: number;
readonly S_IRWXO: number;
readonly S_IROTH: number;
readonly S_IWOTH: number;
readonly S_IXOTH: number;
};
/* A stat(2) snapshot (statSync follows symlinks, lstatSync does not —
* Node's split) — immutable; the supported surface is exactly these
* members. dev/ino identify the filesystem entry, blocks is the allocated
* size in 512-byte units, and the time fields are milliseconds with their
* sub-second fractions. */
export interface Stats {
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
isBlockDevice(): boolean;
isCharacterDevice(): boolean;
isFIFO(): boolean;
isSocket(): boolean;
readonly dev: number;
readonly mode: number;
readonly nlink: number;
readonly uid: number;
readonly gid: number;
readonly rdev: number;
readonly blksize: number;
readonly ino: number;
readonly size: number;
readonly blocks: number;
readonly atimeMs: number;
readonly mtimeMs: number;
readonly ctimeMs: number;
readonly birthtimeMs: number;
readonly atime: Date;
readonly mtime: Date;
readonly ctime: Date;
readonly birthtime: Date;
}
/* throwIfNoEntry: false answers undefined for a missing entry (ENOENT or
* ENOTDIR) instead of throwing. BigIntStats (bigint: true) has no
* lowering. */
export interface StatSyncOptions {
bigint?: boolean;
throwIfNoEntry?: boolean;
}
export function statSync(path: string | URL, options?: undefined): Stats;
export function statSync(
path: string | URL,
options: StatSyncOptions & { bigint?: false; throwIfNoEntry: false },
): Stats | undefined;
export function statSync(
path: string | URL,
options: StatSyncOptions & { bigint?: false; throwIfNoEntry?: true },
): Stats;
/* bigint: true type-checks so the lowering can name it as unsupported. */
export function statSync(path: string | URL, options: StatSyncOptions & { bigint: true }): Stats;
export function statSync(path: string | URL, options: StatSyncOptions): Stats | undefined;
export function lstatSync(path: string | URL, options?: undefined): Stats;
export function lstatSync(
path: string | URL,
options: StatSyncOptions & { bigint?: false; throwIfNoEntry: false },
): Stats | undefined;
export function lstatSync(
path: string | URL,
options: StatSyncOptions & { bigint?: false; throwIfNoEntry?: true },
): Stats;
/* bigint: true type-checks so the lowering can name it as unsupported. */
export function lstatSync(path: string | URL, options: StatSyncOptions & { bigint: true }): Stats;
export function lstatSync(path: string | URL, options: StatSyncOptions): Stats | undefined;
/* The fd pair behind spawn's fd-stdio form: openSync(path, flags) →
* the raw fd. Numeric flags use an inline OR of the O_* constants. */
export function openSync(path: string | URL, flags: string): number;
export function openSync(path: string | URL, flags: number, mode?: number): number;
export function closeSync(fd: number): void;
export function fdatasyncSync(fd: number): void;
export function ftruncateSync(fd: number, len?: number): void;
export function utimesSync(
path: string | Uint8Array | URL,
atime: number | string | Date,
mtime: number | string | Date,
): void;
export function futimesSync(
fd: number,
atime: number | string | Date,
mtime: number | string | Date,
): void;
export function lutimesSync(
path: string | Uint8Array | URL,
atime: number | string | Date,
mtime: number | string | Date,
): void;
export function utimes(
path: string | Uint8Array | URL,
atime: number | string | Date,
mtime: number | string | Date,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function futimes(
fd: number,
atime: number | string | Date,
mtime: number | string | Date,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function lutimes(
path: string | Uint8Array | URL,
atime: number | string | Date,
mtime: number | string | Date,
callback: (err: NodeJS.ErrnoException | null) => void,
): void;
export function readvSync(fd: number, buffers: Uint8Array[], position?: number | null): number;
export function writevSync(fd: number, buffers: Uint8Array[], position?: number | null): number;
/* Read into a caller buffer from the fd's current position when position
* is omitted/null, or from a numeric byte position without advancing the
* fd. Answers the byte count, 0 at EOF. */
export interface ReadSyncOptions {
offset?: number;
length?: number;
position?: number | null;
}
export function readSync(fd: number, buffer: Uint8Array, options?: ReadSyncOptions): number;
export function readSync(
fd: number,
buffer: Uint8Array,
offset: number,
length: number,
position?: number | null,
): number;
/* Write a caller-buffer window, or a utf8 string, at the fd's current
* position when position is omitted/null (advancing it), or at a numeric
* byte position without advancing it. Answers the byte count. */
export interface WriteSyncOptions {
offset?: number;
length?: number;
position?: number | null;
}
export function writeSync(fd: number, buffer: Uint8Array, options: WriteSyncOptions): number;
export function writeSync(
fd: number,
buffer: Uint8Array,
offset?: number,
length?: number,
position?: number | null,
): number;
export function writeSync(
fd: number,
string: string,
position?: number | null,
encoding?: "utf8" | "utf-8",
): number;
/* statSync over an open fd — the same Stats snapshot. */
export function fstatSync(fd: number): Stats;
/* realpath(3) — resolves symlinks, `.`/`..`, throwing Node's fs error
* shapes for missing paths. */
export function realpathSync(path: string | URL): string;
export namespace realpathSync {
function native(path: string | URL): string;
}
/* statfs(2)/statvfs(3) — the filesystem-capacity snapshot (the fields
* Node's statfsSync reports; bavail × bsize is the free-space probe). */
export interface StatsFsBase<T> {
type: T;
bsize: T;
blocks: T;
bfree: T;
bavail: T;
files: T;
ffree: T;
}
export interface StatsFs extends StatsFsBase<number> {}
export interface BigIntStatsFs extends StatsFsBase<bigint> {}
export interface StatFsOptions {
bigint?: boolean;
}
export function statfsSync(
path: string | Uint8Array | URL,
options?: StatFsOptions & { bigint?: false },
): StatsFs;
export function statfsSync(
path: string | Uint8Array | URL,
options: StatFsOptions & { bigint: true },
): BigIntStatsFs;
export function statfsSync(
path: string | Uint8Array | URL,
options?: StatFsOptions,
): StatsFs | BigIntStatsFs;
export function statfs(
path: string | Uint8Array | URL,
callback: (err: NodeJS.ErrnoException | null, stats: StatsFs) => void,
): void;
export function statfs(
path: string | Uint8Array | URL,
options: (StatFsOptions & { bigint?: false }) | undefined,
callback: (err: NodeJS.ErrnoException | null, stats: StatsFs) => void,
): void;
export function statfs(
path: string | Uint8Array | URL,
options: StatFsOptions & { bigint: true },
callback: (err: NodeJS.ErrnoException | null, stats: BigIntStatsFs) => void,
): void;
export function statfs(
path: string | Uint8Array | URL,
options: StatFsOptions | undefined,
callback: (err: NodeJS.ErrnoException | null, stats: StatsFs | BigIntStatsFs) => void,
): void;
/* fs.watch — the file-watching slice (scr_watch.c, kqueue EVFILT_VNODE):
* "rename"/"change" events on ONE path, watcher.close() to stop. The
* listener takes zero parameters or the eventType string (the filename
* parameter has no lowering); an open watcher keeps the loop alive. A
* path that cannot be opened THROWS Node's fs error synchronously. */
export interface FSWatcher {
close(): void;
}
/* The options-record stance (see http.RequestOptions): persistent: true,
* recursive: false, and encoding: "utf8" state the lowered behavior and
* are accepted; persistent: false, recursive: true, and signal fence by
* name at the call site; undocumented keys drop like Node. */
export interface WatchOptions {
persistent?: boolean;
recursive?: boolean;
encoding?: string;
[option: string]: unknown;
}
export function watch(path: string, listener?: (eventType: string) => void): FSWatcher;
export function watch(
path: string,
options: WatchOptions,
listener?: (eventType: string) => void,
): FSWatcher;
/* fs.promises IS the fs/promises module (Node's rule) — the namespace-
* import form `fs.promises.readFile(...)` lowers through the same
* fs/promises table as `import { readFile } from "node:fs/promises"`. */
export const promises: typeof import("node:fs/promises");
}
/* Every builtin answers to BOTH specifier forms, like in Node: the bare
* module re-exports its node:-prefixed twin (or holds the declarations
* itself — one of the pair forwards). The lowerer recognizes members by
* their import SPECIFIER, so both forms lower identically. */
declare module "fs" {
export * from "node:fs";
}
@@ -0,0 +1,9 @@
/// <reference path="./fs.d.ts" />
/* graceful-fs — served as node:fs (it monkeypatches fs and retries on
* EMFILE/ENFILE; compiled programs call fs directly, without the retry
* queue). gracefulify is a no-op statement. The @types/graceful-fs shape. */
declare module "graceful-fs" {
export * from "node:fs";
export function gracefulify<T>(fsModule: T): T;
}
+326
View File
@@ -0,0 +1,326 @@
/// <reference path="./http2.d.ts" />
/// <reference path="./net.d.ts" />
/* node:http — the SERVER and CLIENT slices (scr_http.c layers a
* hand-written HTTP/1.1 parser + serializer on scr_net.c; both link only
* into using binaries). createServer(handler) returns a net.Server —
* listen/close/address().port/'error' are the same lowered surface. The
* request carries url/method (always present on server requests),
* statusCode (a number on client responses, undefined on server
* requests), the underlying socket, and lowercased headers read as
* `string | undefined`; the body streams through on("data"/"end"). The
* response is setHeader/writeHead/write/end/destroy with Node's framing
* (Content-Length for a single end(body), chunked after writeHead/write)
* and the auto Date/Connection headers; writeHead's headers argument is
* an object literal or a Record<string, string>. request/get dial one
* connection per call (no agent pooling) with Node's exact wire head. */
declare module "http" {
import { Server as NetServer, Socket } from "net";
export const METHODS: string[];
export const STATUS_CODES: { [status: number]: string | undefined };
export const maxHeaderSize: number;
export interface Server extends NetServer {
timeout: number;
setTimeout(msecs: number, callback?: (socket: Socket) => void): this;
closeAllConnections(): void;
closeIdleConnections(): void;
keepAliveTimeout: number;
keepAliveTimeoutBuffer: number;
headersTimeout: number;
requestTimeout: number;
}
export type RequestListener = (req: IncomingMessage, res: ServerResponse) => void;
/* The Server VALUE — Node's constructor works with and without `new`
* (test/parallel's http.Server(fn) spelling); both route to the
* createServer lowering. */
export const Server: {
new (requestListener?: (req: IncomingMessage, res: ServerResponse) => void): Server;
new (
options: ServerOptions,
requestListener?: (req: IncomingMessage, res: ServerResponse) => void,
): Server;
(requestListener?: (req: IncomingMessage, res: ServerResponse) => void): Server;
(
options: ServerOptions,
requestListener?: (req: IncomingMessage, res: ServerResponse) => void,
): Server;
};
/* The options-record stance (the RequestOptions precedent): every
* documented key typechecks; the lowering's option walk decides per
* key — requireHostHeader: false, joinDuplicateHeaders, and
* keepAliveTimeoutBuffer lower,
* documented-but-unlowered keys fence by name, unknown keys drop. */
export interface ServerOptions {
requireHostHeader?: boolean;
joinDuplicateHeaders?: boolean;
keepAliveTimeoutBuffer?: number;
maxHeaderSize?: number;
[option: string]: unknown;
}
/* The outgoing-header shape, @types/node's matrix: numbers format via
* String(n), arrays write one line per element (set-cookie's shape).
* Incoming headers stay `string | undefined` — what the parser answers
* (under @types/node the two SLOTS unify so `{ ...req.headers }`
* merges into outgoing literals as a copy; the fallback keeps reads
* simple and spreads target the same string | undefined slot). */
export type OutgoingHttpHeaders = { [name: string]: number | string | string[] | undefined };
export interface IncomingMessage {
readonly url: string;
readonly method: string;
readonly httpVersion: string;
readonly complete: boolean;
readonly aborted: boolean;
readonly statusCode: number | undefined;
readonly statusMessage: string | undefined;
readonly socket: Socket;
readonly connection: Socket;
readonly headers: { [name: string]: string | undefined };
readonly headersDistinct: { [name: string]: string[] | undefined };
readonly rawHeaders: string[];
readonly trailers: { [name: string]: string | undefined };
readonly trailersDistinct: { [name: string]: string[] | undefined };
readonly rawTrailers: string[];
resume(): void;
pause(): void;
destroy(): void;
setTimeout(msecs: number, callback?: () => void): this;
/* setEncoding('utf8'): 'data' delivers strings (other real encodings
* throw a "not supported yet" Error at runtime; unknown names throw
* ERR_UNKNOWN_ENCODING). */
setEncoding(encoding: string): void;
/* The proxy legs: the body streams into a ServerResponse, a
* ClientRequest, or a raw Socket; natural end ends the destination. */
pipe(
destination: ServerResponse | import("http2").Http2ServerResponse | ClientRequest | Socket,
): void;
on(event: "data", listener: (chunk: any) => void): void;
on(event: "end" | "close" | "aborted", listener: () => void): void;
on(event: "error", listener: (err: Error) => void): void;
/* addListener IS on (Node aliases them) — the suite spells both. */
addListener(event: "data", listener: (chunk: any) => void): void;
addListener(event: "end" | "close" | "aborted", listener: () => void): void;
addListener(event: "error", listener: (err: Error) => void): void;
once(event: "data", listener: (chunk: any) => void): void;
once(event: "end" | "close" | "aborted", listener: () => void): void;
once(event: "error", listener: (err: Error) => void): void;
}
export interface ServerResponse {
readonly headersSent: boolean;
readonly writableEnded: boolean;
readonly finished: boolean;
readonly writableFinished: boolean;
readonly writableCorked: number;
readonly req: IncomingMessage;
readonly socket: Socket | null;
readonly connection: Socket | null;
sendDate: boolean;
strictContentLength: boolean;
/* Node's writable head properties: the implicit head reads them. */
statusCode: number;
statusMessage: string | undefined;
/* The value keeps its type: getHeader answers the number, string or
* array that was set. */
setHeader(name: string, value: number | string | readonly string[]): void;
appendHeader(name: string, value: string | readonly string[]): void;
getHeader(name: string): number | string | string[] | undefined;
getHeaderNames(): string[];
getRawHeaderNames(): string[];
getHeaders(): OutgoingHttpHeaders;
hasHeader(name: string): boolean;
removeHeader(name: string): void;
/* Both overloads answer the response (`return this` chaining); the
* headers argument also takes Node's flat [name, value, ...] array. */
writeHead(statusCode: number, headers?: OutgoingHttpHeaders | string[]): ServerResponse;
writeHead(
statusCode: number,
statusMessage: string,
headers?: OutgoingHttpHeaders | string[],
): ServerResponse;
writeContinue(callback?: () => void): void;
writeProcessing(callback?: () => void): void;
writeEarlyHints(hints: Record<string, string | string[]>, callback?: () => void): void;
write(data: string | Uint8Array): void;
flushHeaders(): void;
cork(): void;
uncork(): void;
addTrailers(headers: OutgoingHttpHeaders | ReadonlyArray<[string, string]>): void;
setTimeout(msecs: number, callback?: () => void): this;
/* end's callback forms fire once the body went out (the 'finish'
* emit, deferred past the handler's synchronous tail). */
end(data?: string | Uint8Array, callback?: () => void): void;
end(callback: () => void): void;
destroy(): void;
on(event: "close" | "finish", listener: () => void): void;
/* addListener IS on (Node aliases them) — the suite spells both. */
addListener(event: "close" | "finish", listener: () => void): void;
once(event: "close" | "finish", listener: () => void): void;
}
/* The CLIENT slice (http.request/http.get): the options-object form
* with hostname/host, port, path, method, timeout, and headers; the
* callback receives the response as an IncomingMessage (statusCode,
* headers, body via on("data"/"end")). */
export interface RequestOptions {
hostname?: string | null;
host?: string | null;
/* A string port (a URL's .port) is accepted, as by Node. */
port?: number | string | null;
path?: string | null;
method?: string;
timeout?: number;
headers?: OutgoingHttpHeaders;
/* The caller's own dialer (the proxy's loopback dial): invoked once,
* synchronously; its socket carries the exchange. */
createConnection?: () => Socket;
/* agent: false is a one-shot dial with Connection: close — exactly
* the compiled client's model; null/undefined are the default; an
* Agent VALUE threads through (getName-keyed maxSockets accounting
* over one-dial-per-request connections). */
agent?: Agent | boolean | null;
/* Aborting destroys the request with an AbortError. */
signal?: AbortSignal;
/* HTTP over the Unix socket at this path instead of host:port. */
socketPath?: string;
/* The options-record stance: Node ignores an options record's
* unknown keys, so every key typechecks here — the option WALK in
* the lowering decides per key (lower, fence by name, or drop
* undocumented keys exactly like Node). */
[option: string]: unknown;
}
/* The Agent lowers to a checked-dynamic HANDLE: option parsing at the
* literal construction site, getName, destroy, the sockets/requests/
* freeSockets snapshots, and REAL maxSockets accounting (over-limit
* requests defer their dial and queue). keepAlive: true keeps finished
* connections in freeSockets for the next request to the same name,
* taken in `scheduling` order. */
export interface AgentOptions {
keepAlive?: boolean;
keepAliveMsecs?: number;
maxSockets?: number;
maxFreeSockets?: number;
maxTotalSockets?: number;
scheduling?: "fifo" | "lifo";
timeout?: number;
port?: number;
[option: string]: unknown;
}
export class Agent {
constructor(options?: AgentOptions);
destroy(): void;
/* Node's exact key shape: host:port:localAddress[:family][:socketPath]. */
getName(options?: {
host?: string;
port?: number;
localAddress?: string;
family?: number;
socketPath?: string;
[option: string]: unknown;
}): string;
maxSockets: number;
maxFreeSockets: number;
keepAliveMsecs: number;
readonly keepAlive: boolean;
readonly protocol: string;
/* Settable — a portless request through this agent dials it (Node's
* option merge). */
defaultPort: number;
readonly totalSocketCount: number;
readonly sockets: { [key: string]: unknown[] };
readonly freeSockets: { [key: string]: unknown[] };
readonly requests: { [key: string]: unknown[] };
}
/* Node's keepAlive global agent for requests without an agent option. */
export const globalAgent: Agent;
export interface ClientRequest {
readonly destroyed: boolean;
readonly aborted: boolean;
readonly socket: Socket;
readonly connection: Socket;
readonly writableCorked: number;
readonly method: string;
readonly path: string;
readonly host: string;
readonly protocol: string;
readonly headersSent: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly finished: boolean;
readonly reusedSocket: boolean;
setHeader(name: string, value: string): void;
getHeader(name: string): string | undefined;
hasHeader(name: string): boolean;
removeHeader(name: string): void;
getHeaderNames(): string[];
getRawHeaderNames(): string[];
getHeaders(): OutgoingHttpHeaders;
flushHeaders(): void;
addTrailers(headers: OutgoingHttpHeaders | ReadonlyArray<[string, string]>): void;
cork(): void;
uncork(): void;
setNoDelay(noDelay?: boolean): void;
setSocketKeepAlive(enable?: boolean, initialDelay?: number): void;
setTimeout(timeout: number, callback?: () => void): this;
write(data: string | Uint8Array): void;
end(data?: string | Uint8Array): void;
destroy(error?: Error): void;
abort(): void;
on(event: "response", listener: (res: IncomingMessage) => void): void;
on(event: "socket", listener: (socket: Socket) => void): void;
on(
event: "upgrade",
listener: (res: IncomingMessage, socket: Socket, head: Buffer) => void,
): void;
on(event: "timeout" | "close" | "finish" | "abort" | "continue", listener: () => void): void;
on(event: "error", listener: (err: Error) => void): void;
/* addListener IS on (Node aliases them) — the suite spells both. */
addListener(event: "response", listener: (res: IncomingMessage) => void): void;
addListener(event: "socket", listener: (socket: Socket) => void): void;
addListener(
event: "upgrade",
listener: (res: IncomingMessage, socket: Socket, head: Buffer) => void,
): void;
addListener(event: "timeout" | "close" | "finish" | "abort", listener: () => void): void;
addListener(event: "error", listener: (err: Error) => void): void;
once(event: "response", listener: (res: IncomingMessage) => void): void;
once(event: "socket", listener: (socket: Socket) => void): void;
once(
event: "upgrade",
listener: (res: IncomingMessage, socket: Socket, head: Buffer) => void,
): void;
once(event: "timeout" | "close" | "finish" | "abort" | "continue", listener: () => void): void;
once(event: "error", listener: (err: Error) => void): void;
}
export function createServer(
requestListener?: (req: IncomingMessage, res: ServerResponse) => void,
): Server;
export function createServer(
options: ServerOptions,
requestListener?: (req: IncomingMessage, res: ServerResponse) => void,
): Server;
/* One signature with a UNION first parameter rather than Node's two
* overloads: `const requestFn = tls ? https.request : http.request`
* (the portless isProxyRunning shape) unions two function types, and
* resolving a call on that union collapses each constituent to a
* single signature — with an overload SET on both sides the options
* literal ends up checked against URL, in either declaration order.
* A union parameter has nothing to collapse. The lowering dispatches
* on the argument's own type, so it reads the same either way.
*
* `target` is a URL string or URL object (the spelling a from-scratch
* client reaches for first — dialed directly, with a non-http scheme
* an ERR_INVALID_PROTOCOL at runtime rather than a type error), or
* the options record. */
export function request(
target: RequestOptions | string | URL,
callback?: (res: IncomingMessage) => void,
): ClientRequest;
export function get(
target: RequestOptions | string | URL,
callback?: (res: IncomingMessage) => void,
): ClientRequest;
export function validateHeaderName(name: string, label?: string): void;
export function validateHeaderValue(name: string, value: unknown): void;
}
declare module "node:http" {
export * from "http";
}
+816
View File
@@ -0,0 +1,816 @@
/// <reference path="./dgram.d.ts" />
/// <reference path="./http.d.ts" />
/// <reference path="./net.d.ts" />
/// <reference path="./tls.d.ts" />
/* node:http2 — the compatibility surface: allowHTTP1 servers negotiate
* h2 or HTTP/1.1 and expose the shared request/response API. HTTP/2
* requests retain their backing stream; server session failures surface
* through sessionError. */
declare module "http2" {
import { Socket } from "net";
export interface Http2Stream {
on(event: "error" | "close", listener: (err: Error) => void): void;
once(event: "error" | "close", listener: (err: Error) => void): void;
addListener(event: "error" | "close", listener: (err: Error) => void): void;
destroy(): void;
}
export interface Http2ServerRequest {
readonly url: string;
readonly method: string;
readonly statusCode: number | undefined;
readonly socket: Socket;
readonly headers: { [name: string]: string | undefined };
readonly stream: Http2Stream;
/* The h2 compat request's version triple ("2.0" over real h2 streams;
* the allowHTTP1 lowering's HTTP/1.1 connections answer 1.x). */
readonly httpVersion: string;
readonly httpVersionMajor: number;
readonly httpVersionMinor: number;
readonly aborted: boolean;
readonly complete: boolean;
resume(): void;
destroy(): void;
setEncoding(encoding: string): void;
pipe(destination: Socket | import("http").ClientRequest): void;
on(event: "data", listener: (chunk: Buffer) => void): void;
on(event: "end" | "close" | "aborted", listener: () => void): void;
on(event: "error", listener: (err: Error) => void): void;
/* addListener IS on (Node aliases them) — and the compat req IS the
* http.IncomingMessage surface, so the alias mirrors here too. */
addListener(event: "data", listener: (chunk: Buffer) => void): void;
addListener(event: "end" | "close" | "aborted", listener: () => void): void;
addListener(event: "error", listener: (err: Error) => void): void;
once(event: "data", listener: (chunk: Buffer) => void): void;
once(event: "end" | "close" | "aborted", listener: () => void): void;
once(event: "error", listener: (err: Error) => void): void;
}
export interface Http2ServerResponse {
readonly headersSent: boolean;
readonly writableEnded: boolean;
readonly writableCorked: number;
/* The same lowered surface as http.ServerResponse — the allowHTTP1
* lowering serves every connection as HTTP/1.1, where the compat
* response IS this parser's response handle. */
statusCode: number;
statusMessage: string;
setHeader(name: string, value: string | number): void;
getHeader(name: string): string | undefined;
getHeaderNames(): string[];
getRawHeaderNames(): string[];
getHeaders(): import("http").OutgoingHttpHeaders;
hasHeader(name: string): boolean;
removeHeader(name: string): void;
writeHead(
statusCode: number,
headers?: import("http").OutgoingHttpHeaders | string[],
): Http2ServerResponse;
writeHead(
statusCode: number,
statusMessage: string,
headers?: import("http").OutgoingHttpHeaders | string[],
): Http2ServerResponse;
writeContinue(): void;
writeEarlyHints(hints: Record<string, string | string[]>): void;
write(data: string | Uint8Array): void;
flushHeaders(): void;
cork(): void;
uncork(): void;
addTrailers(
headers: import("http").OutgoingHttpHeaders | ReadonlyArray<[string, string]>,
): void;
end(data?: string | Uint8Array, callback?: () => void): void;
end(callback: () => void): void;
destroy(): void;
on(event: "close", listener: () => void): void;
/* addListener IS on (Node aliases them) — and the compat res IS the
* http.ServerResponse surface (assignability into ServerResponse
* unions — IncomingMessage.pipe's destination — needs the alias). */
addListener(event: "close", listener: () => void): void;
once(event: "close", listener: () => void): void;
}
export interface Http2SecureServer {
listen(port: number, callback?: () => void): void;
close(callback?: () => void): void;
/* The bound AddressInfo (Node answers null before listen — this
* surface answers the record with port 0 there, the serverPort
* stance). */
address(): import("node:dgram").AddressInfo;
emit(event: "connection", socket: Socket): void;
on(event: "connection", listener: (socket: Socket) => void): void;
on(
event: "request",
listener: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): void;
on(event: "error", listener: (err: Error) => void): void;
on(event: "close", listener: () => void): void;
on(event: "sessionError", listener: (err: Error, session: ServerHttp2Session) => void): void;
/* The ALPN=h2 server's surface (createSecureServer WITHOUT
* allowHTTP1 — the real h2-over-TLS stack): per-stream and
* per-session listeners, exactly the h2c server's. */
on(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
on(event: "session", listener: (session: ServerHttp2Session) => void): void;
/* HTTP CONNECT (and, in Node, the h2 extended CONNECT — which the
* allowHTTP1 lowering never sees): the second argument is the raw
* socket on HTTP/1.1 connections; narrow with instanceof. */
on(
event: "connect",
listener: (
req: Http2ServerRequest | import("http").IncomingMessage,
resOrSocket: Http2ServerResponse | Socket,
) => void,
): void;
once(event: "connection", listener: (socket: Socket) => void): void;
once(
event: "request",
listener: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): void;
once(event: "error", listener: (err: Error) => void): void;
once(event: "close", listener: () => void): void;
once(event: "sessionError", listener: (err: Error, session: ServerHttp2Session) => void): void;
once(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
once(event: "session", listener: (session: ServerHttp2Session) => void): void;
once(
event: "connect",
listener: (
req: Http2ServerRequest | import("http").IncomingMessage,
resOrSocket: Http2ServerResponse | Socket,
) => void,
): void;
addListener(event: "connection", listener: (socket: Socket) => void): void;
addListener(
event: "request",
listener: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(event: "close", listener: () => void): void;
addListener(
event: "sessionError",
listener: (err: Error, session: ServerHttp2Session) => void,
): void;
addListener(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
addListener(event: "session", listener: (session: ServerHttp2Session) => void): void;
addListener(
event: "connect",
listener: (
req: Http2ServerRequest | import("http").IncomingMessage,
resOrSocket: Http2ServerResponse | Socket,
) => void,
): void;
}
export interface SecureServerOptions {
allowHTTP1?: boolean;
cert?: string | Uint8Array;
key?: string | Uint8Array;
SNICallback?: (
servername: string,
cb: (err: Error | null, ctx?: import("tls").SecureContext) => void,
) => void;
/* The options-record stance (see http.RequestOptions): h2 session-
* tuning knobs are accepted as literals and ignored (no h2 session
* ever exists under the allowHTTP1 lowering); other documented keys
* fence by name; undocumented keys drop like Node. */
[option: string]: unknown;
}
/* The full Node v24 constants table (240 members), literal-typed so
* computed header keys ([HTTP2_HEADER_PATH]: value) stay literal keys.
* Every ACCESS bakes as its literal at lowering; the object itself
* never materializes (bare http2.constants value uses fence). */
export interface Http2Constants {
readonly NGHTTP2_ERR_FRAME_SIZE_ERROR: -522;
readonly NGHTTP2_SESSION_SERVER: 0;
readonly NGHTTP2_SESSION_CLIENT: 1;
readonly NGHTTP2_STREAM_STATE_IDLE: 1;
readonly NGHTTP2_STREAM_STATE_OPEN: 2;
readonly NGHTTP2_STREAM_STATE_RESERVED_LOCAL: 3;
readonly NGHTTP2_STREAM_STATE_RESERVED_REMOTE: 4;
readonly NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: 5;
readonly NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: 6;
readonly NGHTTP2_STREAM_STATE_CLOSED: 7;
readonly NGHTTP2_FLAG_NONE: 0;
readonly NGHTTP2_FLAG_END_STREAM: 1;
readonly NGHTTP2_FLAG_END_HEADERS: 4;
readonly NGHTTP2_FLAG_ACK: 1;
readonly NGHTTP2_FLAG_PADDED: 8;
readonly NGHTTP2_FLAG_PRIORITY: 32;
readonly DEFAULT_SETTINGS_HEADER_TABLE_SIZE: 4096;
readonly DEFAULT_SETTINGS_ENABLE_PUSH: 1;
readonly DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS: 4294967295;
readonly DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE: 65535;
readonly DEFAULT_SETTINGS_MAX_FRAME_SIZE: 16384;
readonly DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE: 65535;
readonly DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL: 0;
readonly MAX_MAX_FRAME_SIZE: 16777215;
readonly MIN_MAX_FRAME_SIZE: 16384;
readonly MAX_INITIAL_WINDOW_SIZE: 2147483647;
readonly NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: 1;
readonly NGHTTP2_SETTINGS_ENABLE_PUSH: 2;
readonly NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: 3;
readonly NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: 4;
readonly NGHTTP2_SETTINGS_MAX_FRAME_SIZE: 5;
readonly NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: 6;
readonly NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: 8;
readonly PADDING_STRATEGY_NONE: 0;
readonly PADDING_STRATEGY_ALIGNED: 1;
readonly PADDING_STRATEGY_MAX: 2;
readonly PADDING_STRATEGY_CALLBACK: 1;
readonly NGHTTP2_NO_ERROR: 0;
readonly NGHTTP2_PROTOCOL_ERROR: 1;
readonly NGHTTP2_INTERNAL_ERROR: 2;
readonly NGHTTP2_FLOW_CONTROL_ERROR: 3;
readonly NGHTTP2_SETTINGS_TIMEOUT: 4;
readonly NGHTTP2_STREAM_CLOSED: 5;
readonly NGHTTP2_FRAME_SIZE_ERROR: 6;
readonly NGHTTP2_REFUSED_STREAM: 7;
readonly NGHTTP2_CANCEL: 8;
readonly NGHTTP2_COMPRESSION_ERROR: 9;
readonly NGHTTP2_CONNECT_ERROR: 10;
readonly NGHTTP2_ENHANCE_YOUR_CALM: 11;
readonly NGHTTP2_INADEQUATE_SECURITY: 12;
readonly NGHTTP2_HTTP_1_1_REQUIRED: 13;
readonly NGHTTP2_DEFAULT_WEIGHT: 16;
readonly HTTP2_HEADER_STATUS: ":status";
readonly HTTP2_HEADER_METHOD: ":method";
readonly HTTP2_HEADER_AUTHORITY: ":authority";
readonly HTTP2_HEADER_SCHEME: ":scheme";
readonly HTTP2_HEADER_PATH: ":path";
readonly HTTP2_HEADER_PROTOCOL: ":protocol";
readonly HTTP2_HEADER_ACCEPT_ENCODING: "accept-encoding";
readonly HTTP2_HEADER_ACCEPT_LANGUAGE: "accept-language";
readonly HTTP2_HEADER_ACCEPT_RANGES: "accept-ranges";
readonly HTTP2_HEADER_ACCEPT: "accept";
readonly HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS: "access-control-allow-credentials";
readonly HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS: "access-control-allow-headers";
readonly HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS: "access-control-allow-methods";
readonly HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: "access-control-allow-origin";
readonly HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS: "access-control-expose-headers";
readonly HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS: "access-control-request-headers";
readonly HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD: "access-control-request-method";
readonly HTTP2_HEADER_AGE: "age";
readonly HTTP2_HEADER_AUTHORIZATION: "authorization";
readonly HTTP2_HEADER_CACHE_CONTROL: "cache-control";
readonly HTTP2_HEADER_CONNECTION: "connection";
readonly HTTP2_HEADER_CONTENT_DISPOSITION: "content-disposition";
readonly HTTP2_HEADER_CONTENT_ENCODING: "content-encoding";
readonly HTTP2_HEADER_CONTENT_LENGTH: "content-length";
readonly HTTP2_HEADER_CONTENT_TYPE: "content-type";
readonly HTTP2_HEADER_COOKIE: "cookie";
readonly HTTP2_HEADER_DATE: "date";
readonly HTTP2_HEADER_ETAG: "etag";
readonly HTTP2_HEADER_FORWARDED: "forwarded";
readonly HTTP2_HEADER_HOST: "host";
readonly HTTP2_HEADER_IF_MODIFIED_SINCE: "if-modified-since";
readonly HTTP2_HEADER_IF_NONE_MATCH: "if-none-match";
readonly HTTP2_HEADER_IF_RANGE: "if-range";
readonly HTTP2_HEADER_LAST_MODIFIED: "last-modified";
readonly HTTP2_HEADER_LINK: "link";
readonly HTTP2_HEADER_LOCATION: "location";
readonly HTTP2_HEADER_RANGE: "range";
readonly HTTP2_HEADER_REFERER: "referer";
readonly HTTP2_HEADER_SERVER: "server";
readonly HTTP2_HEADER_SET_COOKIE: "set-cookie";
readonly HTTP2_HEADER_STRICT_TRANSPORT_SECURITY: "strict-transport-security";
readonly HTTP2_HEADER_TRANSFER_ENCODING: "transfer-encoding";
readonly HTTP2_HEADER_TE: "te";
readonly HTTP2_HEADER_UPGRADE_INSECURE_REQUESTS: "upgrade-insecure-requests";
readonly HTTP2_HEADER_UPGRADE: "upgrade";
readonly HTTP2_HEADER_USER_AGENT: "user-agent";
readonly HTTP2_HEADER_VARY: "vary";
readonly HTTP2_HEADER_X_CONTENT_TYPE_OPTIONS: "x-content-type-options";
readonly HTTP2_HEADER_X_FRAME_OPTIONS: "x-frame-options";
readonly HTTP2_HEADER_KEEP_ALIVE: "keep-alive";
readonly HTTP2_HEADER_PROXY_CONNECTION: "proxy-connection";
readonly HTTP2_HEADER_X_XSS_PROTECTION: "x-xss-protection";
readonly HTTP2_HEADER_ALT_SVC: "alt-svc";
readonly HTTP2_HEADER_CONTENT_SECURITY_POLICY: "content-security-policy";
readonly HTTP2_HEADER_EARLY_DATA: "early-data";
readonly HTTP2_HEADER_EXPECT_CT: "expect-ct";
readonly HTTP2_HEADER_ORIGIN: "origin";
readonly HTTP2_HEADER_PURPOSE: "purpose";
readonly HTTP2_HEADER_TIMING_ALLOW_ORIGIN: "timing-allow-origin";
readonly HTTP2_HEADER_X_FORWARDED_FOR: "x-forwarded-for";
readonly HTTP2_HEADER_PRIORITY: "priority";
readonly HTTP2_HEADER_ACCEPT_CHARSET: "accept-charset";
readonly HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE: "access-control-max-age";
readonly HTTP2_HEADER_ALLOW: "allow";
readonly HTTP2_HEADER_CONTENT_LANGUAGE: "content-language";
readonly HTTP2_HEADER_CONTENT_LOCATION: "content-location";
readonly HTTP2_HEADER_CONTENT_MD5: "content-md5";
readonly HTTP2_HEADER_CONTENT_RANGE: "content-range";
readonly HTTP2_HEADER_DNT: "dnt";
readonly HTTP2_HEADER_EXPECT: "expect";
readonly HTTP2_HEADER_EXPIRES: "expires";
readonly HTTP2_HEADER_FROM: "from";
readonly HTTP2_HEADER_IF_MATCH: "if-match";
readonly HTTP2_HEADER_IF_UNMODIFIED_SINCE: "if-unmodified-since";
readonly HTTP2_HEADER_MAX_FORWARDS: "max-forwards";
readonly HTTP2_HEADER_PREFER: "prefer";
readonly HTTP2_HEADER_PROXY_AUTHENTICATE: "proxy-authenticate";
readonly HTTP2_HEADER_PROXY_AUTHORIZATION: "proxy-authorization";
readonly HTTP2_HEADER_REFRESH: "refresh";
readonly HTTP2_HEADER_RETRY_AFTER: "retry-after";
readonly HTTP2_HEADER_TRAILER: "trailer";
readonly HTTP2_HEADER_TK: "tk";
readonly HTTP2_HEADER_VIA: "via";
readonly HTTP2_HEADER_WARNING: "warning";
readonly HTTP2_HEADER_WWW_AUTHENTICATE: "www-authenticate";
readonly HTTP2_HEADER_HTTP2_SETTINGS: "http2-settings";
readonly HTTP2_METHOD_ACL: "ACL";
readonly HTTP2_METHOD_BASELINE_CONTROL: "BASELINE-CONTROL";
readonly HTTP2_METHOD_BIND: "BIND";
readonly HTTP2_METHOD_CHECKIN: "CHECKIN";
readonly HTTP2_METHOD_CHECKOUT: "CHECKOUT";
readonly HTTP2_METHOD_CONNECT: "CONNECT";
readonly HTTP2_METHOD_COPY: "COPY";
readonly HTTP2_METHOD_DELETE: "DELETE";
readonly HTTP2_METHOD_GET: "GET";
readonly HTTP2_METHOD_HEAD: "HEAD";
readonly HTTP2_METHOD_LABEL: "LABEL";
readonly HTTP2_METHOD_LINK: "LINK";
readonly HTTP2_METHOD_LOCK: "LOCK";
readonly HTTP2_METHOD_MERGE: "MERGE";
readonly HTTP2_METHOD_MKACTIVITY: "MKACTIVITY";
readonly HTTP2_METHOD_MKCALENDAR: "MKCALENDAR";
readonly HTTP2_METHOD_MKCOL: "MKCOL";
readonly HTTP2_METHOD_MKREDIRECTREF: "MKREDIRECTREF";
readonly HTTP2_METHOD_MKWORKSPACE: "MKWORKSPACE";
readonly HTTP2_METHOD_MOVE: "MOVE";
readonly HTTP2_METHOD_OPTIONS: "OPTIONS";
readonly HTTP2_METHOD_ORDERPATCH: "ORDERPATCH";
readonly HTTP2_METHOD_PATCH: "PATCH";
readonly HTTP2_METHOD_POST: "POST";
readonly HTTP2_METHOD_PRI: "PRI";
readonly HTTP2_METHOD_PROPFIND: "PROPFIND";
readonly HTTP2_METHOD_PROPPATCH: "PROPPATCH";
readonly HTTP2_METHOD_PUT: "PUT";
readonly HTTP2_METHOD_REBIND: "REBIND";
readonly HTTP2_METHOD_REPORT: "REPORT";
readonly HTTP2_METHOD_SEARCH: "SEARCH";
readonly HTTP2_METHOD_TRACE: "TRACE";
readonly HTTP2_METHOD_UNBIND: "UNBIND";
readonly HTTP2_METHOD_UNCHECKOUT: "UNCHECKOUT";
readonly HTTP2_METHOD_UNLINK: "UNLINK";
readonly HTTP2_METHOD_UNLOCK: "UNLOCK";
readonly HTTP2_METHOD_UPDATE: "UPDATE";
readonly HTTP2_METHOD_UPDATEREDIRECTREF: "UPDATEREDIRECTREF";
readonly HTTP2_METHOD_VERSION_CONTROL: "VERSION-CONTROL";
readonly HTTP_STATUS_CONTINUE: 100;
readonly HTTP_STATUS_SWITCHING_PROTOCOLS: 101;
readonly HTTP_STATUS_PROCESSING: 102;
readonly HTTP_STATUS_EARLY_HINTS: 103;
readonly HTTP_STATUS_OK: 200;
readonly HTTP_STATUS_CREATED: 201;
readonly HTTP_STATUS_ACCEPTED: 202;
readonly HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: 203;
readonly HTTP_STATUS_NO_CONTENT: 204;
readonly HTTP_STATUS_RESET_CONTENT: 205;
readonly HTTP_STATUS_PARTIAL_CONTENT: 206;
readonly HTTP_STATUS_MULTI_STATUS: 207;
readonly HTTP_STATUS_ALREADY_REPORTED: 208;
readonly HTTP_STATUS_IM_USED: 226;
readonly HTTP_STATUS_MULTIPLE_CHOICES: 300;
readonly HTTP_STATUS_MOVED_PERMANENTLY: 301;
readonly HTTP_STATUS_FOUND: 302;
readonly HTTP_STATUS_SEE_OTHER: 303;
readonly HTTP_STATUS_NOT_MODIFIED: 304;
readonly HTTP_STATUS_USE_PROXY: 305;
readonly HTTP_STATUS_TEMPORARY_REDIRECT: 307;
readonly HTTP_STATUS_PERMANENT_REDIRECT: 308;
readonly HTTP_STATUS_BAD_REQUEST: 400;
readonly HTTP_STATUS_UNAUTHORIZED: 401;
readonly HTTP_STATUS_PAYMENT_REQUIRED: 402;
readonly HTTP_STATUS_FORBIDDEN: 403;
readonly HTTP_STATUS_NOT_FOUND: 404;
readonly HTTP_STATUS_METHOD_NOT_ALLOWED: 405;
readonly HTTP_STATUS_NOT_ACCEPTABLE: 406;
readonly HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: 407;
readonly HTTP_STATUS_REQUEST_TIMEOUT: 408;
readonly HTTP_STATUS_CONFLICT: 409;
readonly HTTP_STATUS_GONE: 410;
readonly HTTP_STATUS_LENGTH_REQUIRED: 411;
readonly HTTP_STATUS_PRECONDITION_FAILED: 412;
readonly HTTP_STATUS_PAYLOAD_TOO_LARGE: 413;
readonly HTTP_STATUS_URI_TOO_LONG: 414;
readonly HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: 415;
readonly HTTP_STATUS_RANGE_NOT_SATISFIABLE: 416;
readonly HTTP_STATUS_EXPECTATION_FAILED: 417;
readonly HTTP_STATUS_TEAPOT: 418;
readonly HTTP_STATUS_MISDIRECTED_REQUEST: 421;
readonly HTTP_STATUS_UNPROCESSABLE_ENTITY: 422;
readonly HTTP_STATUS_LOCKED: 423;
readonly HTTP_STATUS_FAILED_DEPENDENCY: 424;
readonly HTTP_STATUS_TOO_EARLY: 425;
readonly HTTP_STATUS_UPGRADE_REQUIRED: 426;
readonly HTTP_STATUS_PRECONDITION_REQUIRED: 428;
readonly HTTP_STATUS_TOO_MANY_REQUESTS: 429;
readonly HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: 431;
readonly HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: 451;
readonly HTTP_STATUS_INTERNAL_SERVER_ERROR: 500;
readonly HTTP_STATUS_NOT_IMPLEMENTED: 501;
readonly HTTP_STATUS_BAD_GATEWAY: 502;
readonly HTTP_STATUS_SERVICE_UNAVAILABLE: 503;
readonly HTTP_STATUS_GATEWAY_TIMEOUT: 504;
readonly HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: 505;
readonly HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: 506;
readonly HTTP_STATUS_INSUFFICIENT_STORAGE: 507;
readonly HTTP_STATUS_LOOP_DETECTED: 508;
readonly HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED: 509;
readonly HTTP_STATUS_NOT_EXTENDED: 510;
readonly HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: 511;
}
export const constants: Http2Constants;
/* The eager handler is the first COMPAT 'request' listener — Node's
* route on either flavor (the allowHTTP1 server's HTTP/1.1 handles,
* the ALPN=h2 server's compat handles over streams). */
export function createSecureServer(
options: SecureServerOptions,
onRequestHandler?: (
req: import("http").IncomingMessage,
res: import("http").ServerResponse,
) => void,
): Http2SecureServer;
/* ── the REAL h2c surface (scr_http2.c: frame codec + HPACK over the
* net loop) — createServer/connect and the session/stream handles the
* Node suite's http2 family exercises. Headers cross as the canonical
* header record (the IncomingHttpHeaders index-signature shape); the
* response :status reads back as a number. Members declared here
* without a lowering fence by name at their use sites. */
/** The http2 module's own header shapes: pure index-signature records
* (the HEADER-FAMILY canonicalization — string[] arm included). */
export interface IncomingHttpHeaders {
[name: string]: number | string | string[] | undefined;
}
export interface OutgoingHttpHeaders {
[name: string]: number | string | string[] | undefined;
}
export interface Http2Session {
close(callback?: () => void): void;
destroy(): void;
readonly closed: boolean;
readonly destroyed: boolean;
readonly encrypted: boolean;
readonly type: number;
readonly alpnProtocol: string;
readonly socket: import("net").Socket;
readonly pendingSettingsAck: boolean;
ref(): void;
unref(): void;
setTimeout(msecs: number, callback?: () => void): void;
ping(callback: (err: Error | null, duration: number, payload: Uint8Array) => void): boolean;
/* The settings surface rides the checked-dynamic machinery (records
* cross as dyn values — the suite's mustCall listeners are dyn). */
settings(settings?: any, callback?: any): void;
readonly localSettings: any;
readonly remoteSettings: any;
goaway(code?: number, lastStreamID?: number, opaqueData?: Uint8Array): void;
on(event: "close" | "timeout", listener: () => void): void;
on(event: "error", listener: (err: Error) => void): void;
on(
event: "connect",
listener: (session: Http2Session, socket: import("net").Socket) => void,
): void;
on(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
on(
event: "goaway",
listener: (errorCode: number, lastStreamID: number, opaqueData?: Uint8Array) => void,
): void;
on(event: "localSettings" | "remoteSettings", listener: (settings: any) => void): void;
on(event: "frameError", listener: (type: number, code: number, id: number) => void): void;
on(event: "ping", listener: (payload: Uint8Array) => void): void;
once(event: "close" | "timeout", listener: () => void): void;
once(event: "error", listener: (err: Error) => void): void;
once(
event: "connect",
listener: (session: Http2Session, socket: import("net").Socket) => void,
): void;
once(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
once(
event: "goaway",
listener: (errorCode: number, lastStreamID: number, opaqueData?: Uint8Array) => void,
): void;
once(event: "localSettings" | "remoteSettings", listener: (settings: any) => void): void;
once(event: "frameError", listener: (type: number, code: number, id: number) => void): void;
once(event: "ping", listener: (payload: Uint8Array) => void): void;
addListener(event: "close" | "timeout", listener: () => void): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(
event: "connect",
listener: (session: Http2Session, socket: import("net").Socket) => void,
): void;
addListener(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
addListener(
event: "goaway",
listener: (errorCode: number, lastStreamID: number, opaqueData?: Uint8Array) => void,
): void;
addListener(event: "localSettings" | "remoteSettings", listener: (settings: any) => void): void;
addListener(
event: "frameError",
listener: (type: number, code: number, id: number) => void,
): void;
addListener(event: "ping", listener: (payload: Uint8Array) => void): void;
}
export interface ClientHttp2Session extends Http2Session {
request(
headers?: OutgoingHttpHeaders,
options?: {
endStream?: boolean;
exclusive?: boolean;
parent?: number;
weight?: number;
waitForTrailers?: boolean;
},
): ClientHttp2Stream;
}
export interface ServerHttp2Session extends Http2Session {
altsvc(alt: string, originOrStream: number | string): void;
origin(...origins: string[]): void;
}
/** The shared Http2Stream core (both roles). 'data' chunks are Buffers
* (strings once setEncoding('utf8') is in force — the IncomingMessage
* chunk:any stance keeps both working). */
interface Http2StreamCore {
readonly id: number | undefined;
readonly rstCode: number;
readonly closed: boolean;
readonly destroyed: boolean;
readonly pending: boolean;
readonly aborted: boolean;
readonly session: Http2Session;
readonly sentHeaders: OutgoingHttpHeaders;
readonly state: Record<string, number>;
write(chunk: string | Uint8Array, callback?: (err?: Error | null) => void): boolean;
end(data?: string | Uint8Array, callback?: () => void): void;
end(callback: () => void): void;
close(code?: number, callback?: () => void): void;
destroy(error?: Error): void;
setEncoding(encoding: string): this;
resume(): void;
pause(): void;
setTimeout(msecs: number, callback?: () => void): void;
priority(options: Record<string, number | boolean>): void;
sendTrailers(headers: OutgoingHttpHeaders): void;
}
export interface ServerHttp2Stream extends Http2StreamCore {
on(event: "data", listener: (chunk: any) => void): void;
on(
event:
| "end"
| "close"
| "aborted"
| "ready"
| "timeout"
| "drain"
| "finish"
| "wantTrailers",
listener: () => void,
): void;
on(event: "error", listener: (err: Error) => void): void;
on(event: "frameError", listener: (type: number, code: number, id: number) => void): void;
on(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): void;
once(event: "data", listener: (chunk: any) => void): void;
once(
event:
| "end"
| "close"
| "aborted"
| "ready"
| "timeout"
| "drain"
| "finish"
| "wantTrailers",
listener: () => void,
): void;
once(event: "error", listener: (err: Error) => void): void;
once(event: "frameError", listener: (type: number, code: number, id: number) => void): void;
once(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): void;
addListener(event: "data", listener: (chunk: any) => void): void;
addListener(
event:
| "end"
| "close"
| "aborted"
| "ready"
| "timeout"
| "drain"
| "finish"
| "wantTrailers",
listener: () => void,
): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(
event: "frameError",
listener: (type: number, code: number, id: number) => void,
): void;
addListener(
event: "trailers",
listener: (trailers: IncomingHttpHeaders, flags: number) => void,
): void;
respond(
headers?: OutgoingHttpHeaders,
options?: { endStream?: boolean; waitForTrailers?: boolean },
): void;
respondWithFile(
path: string,
headers?: OutgoingHttpHeaders,
options?: Record<string, unknown>,
): void;
respondWithFD(
fd: number,
headers?: OutgoingHttpHeaders,
options?: Record<string, unknown>,
): void;
pushStream(
headers: OutgoingHttpHeaders,
callback: (
err: Error | null,
pushStream: ServerHttp2Stream,
headers: OutgoingHttpHeaders,
) => void,
): void;
readonly headersSent: boolean;
readonly pushAllowed: boolean;
additionalHeaders(headers: OutgoingHttpHeaders): void;
}
export interface ClientHttp2Stream extends Http2StreamCore {
on(event: "response", listener: (headers: IncomingHttpHeaders, flags: number) => void): void;
on(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): void;
on(event: "headers", listener: (headers: IncomingHttpHeaders, flags: number) => void): void;
on(event: "data", listener: (chunk: any) => void): void;
on(
event:
| "end"
| "close"
| "aborted"
| "ready"
| "timeout"
| "drain"
| "finish"
| "wantTrailers",
listener: () => void,
): void;
on(event: "error", listener: (err: Error) => void): void;
on(event: "frameError", listener: (type: number, code: number, id: number) => void): void;
on(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): void;
once(event: "response", listener: (headers: IncomingHttpHeaders, flags: number) => void): void;
once(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): void;
once(event: "headers", listener: (headers: IncomingHttpHeaders, flags: number) => void): void;
once(event: "data", listener: (chunk: any) => void): void;
once(
event:
| "end"
| "close"
| "aborted"
| "ready"
| "timeout"
| "drain"
| "finish"
| "wantTrailers",
listener: () => void,
): void;
once(event: "error", listener: (err: Error) => void): void;
once(event: "frameError", listener: (type: number, code: number, id: number) => void): void;
once(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): void;
addListener(
event: "response",
listener: (headers: IncomingHttpHeaders, flags: number) => void,
): void;
addListener(
event: "push",
listener: (headers: IncomingHttpHeaders, flags: number) => void,
): void;
addListener(
event: "headers",
listener: (headers: IncomingHttpHeaders, flags: number) => void,
): void;
addListener(event: "data", listener: (chunk: any) => void): void;
addListener(
event:
| "end"
| "close"
| "aborted"
| "ready"
| "timeout"
| "drain"
| "finish"
| "wantTrailers",
listener: () => void,
): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(
event: "frameError",
listener: (type: number, code: number, id: number) => void,
): void;
addListener(
event: "trailers",
listener: (trailers: IncomingHttpHeaders, flags: number) => void,
): void;
}
export interface Http2Server {
listen(port?: number, callback?: () => void): void;
listen(port: number, host: string, callback?: () => void): void;
close(callback?: () => void): void;
address(): import("node:dgram").AddressInfo;
setTimeout(msecs?: number, callback?: () => void): void;
ref(): void;
unref(): void;
on(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
on(event: "session", listener: (session: ServerHttp2Session) => void): void;
on(
event: "request",
listener: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): void;
on(event: "error", listener: (err: Error) => void): void;
on(event: "close" | "listening" | "timeout", listener: () => void): void;
on(event: "connection", listener: (socket: import("net").Socket) => void): void;
on(event: "sessionError", listener: (err: Error, session: ServerHttp2Session) => void): void;
once(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
once(event: "session", listener: (session: ServerHttp2Session) => void): void;
once(
event: "request",
listener: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): void;
once(event: "error", listener: (err: Error) => void): void;
once(event: "close" | "listening" | "timeout", listener: () => void): void;
once(event: "connection", listener: (socket: import("net").Socket) => void): void;
once(event: "sessionError", listener: (err: Error, session: ServerHttp2Session) => void): void;
addListener(
event: "stream",
listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void,
): void;
addListener(event: "session", listener: (session: ServerHttp2Session) => void): void;
addListener(
event: "request",
listener: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(event: "close" | "listening" | "timeout", listener: () => void): void;
addListener(event: "connection", listener: (socket: import("net").Socket) => void): void;
addListener(
event: "sessionError",
listener: (err: Error, session: ServerHttp2Session) => void,
): void;
}
export interface ServerOptions {
[option: string]: unknown;
}
export function createServer(
onRequestHandler?: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): Http2Server;
export function createServer(
options: ServerOptions,
onRequestHandler?: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
): Http2Server;
export function connect(
authority: string,
listener?: (session: ClientHttp2Session, socket: import("net").Socket) => void,
): ClientHttp2Session;
export function connect(
authority: string,
options: Record<string, unknown>,
listener?: (session: ClientHttp2Session, socket: import("net").Socket) => void,
): ClientHttp2Session;
export function getDefaultSettings(): any;
export function getPackedSettings(settings: Record<string, number | boolean>): Uint8Array;
export const sensitiveHeaders: unique symbol;
}
declare module "node:http2" {
export * from "http2";
}
+59
View File
@@ -0,0 +1,59 @@
/// <reference path="./http.d.ts" />
/* node:https — http over the TLS transport (scr_tls.c).
* createServer({ cert, key }, handler) is the http server behind a
* handshake; request/get are the http client with port 443 default and
* the local-CA knobs: `ca` (PEM string/Buffer) replaces the trust
* anchors, rejectUnauthorized: false disables verification (the
* self-signed probe shape). With neither, /etc/ssl/cert.pem stands in
* for Node's bundled roots. */
declare module "https" {
import { Server } from "http";
import { Agent, ClientRequest, IncomingMessage, ServerResponse } from "http";
export { Agent, Server };
/* Node's keepAlive global agent for requests without an agent option. */
export const globalAgent: Agent;
export interface ServerOptions {
cert: string | Uint8Array;
key: string | Uint8Array;
/* The options-record stance (see http.RequestOptions). */
[option: string]: unknown;
}
export interface RequestOptions {
hostname?: string;
host?: string;
port?: number;
path?: string;
method?: string;
timeout?: number;
headers?: { [name: string]: string };
rejectUnauthorized?: boolean;
ca?: string | Uint8Array;
agent?: Agent | boolean | null;
/* Aborting destroys the request with an AbortError. */
signal?: AbortSignal;
socketPath?: string;
/* The options-record stance (see http.RequestOptions). */
[option: string]: unknown;
}
export function createServer(
options: ServerOptions,
requestListener: (req: IncomingMessage, res: ServerResponse) => void,
): Server;
/* One signature with a union first parameter, for the request-fn
* ternary's sake (see the http block). A URL target takes no options,
* which means Node's defaults — the certificate is verified against
* the default trust anchors. */
export function request(
target: RequestOptions | string | URL,
callback?: (res: IncomingMessage) => void,
): ClientRequest;
export function get(
target: RequestOptions | string | URL,
callback?: (res: IncomingMessage) => void,
): ClientRequest;
}
declare module "node:https" {
export * from "https";
}
+10
View File
@@ -0,0 +1,10 @@
declare module "node:module" {
export function createRequire(filename: string | URL): ScriptcRequire;
export const builtinModules: string[];
export function isBuiltin(moduleName: string): boolean;
export function syncBuiltinESMExports(): void;
}
declare module "module" {
export * from "node:module";
}
+368
View File
@@ -0,0 +1,368 @@
/// <reference path="./dgram.d.ts" />
/// <reference path="./dns.d.ts" />
/// <reference path="./http.d.ts" />
/// <reference path="./http2.d.ts" />
/// <reference path="./tls.d.ts" />
/* node:net — the inbound-networking slice (scr_net.c links only into
* net-using binaries). TCP only, Node's shapes narrowed to what lowers:
* createServer with an optional connection handler; listen(port[, cb])
* with the real port discoverable as address().port (the composed read
* is the lowered form — bare address() has no lowering); close([cb])
* firing once connections drain; socket write/end/destroy/pipe and the
* data/end/close/error/connect/drain events (on and once — listeners
* take at most the declared parameter). write returns Node's
* backpressure boolean; end returns void here (Node returns the socket);
* on/once return void (chaining is fenced). connect's host is a numeric IP or "localhost" (pinned to
* 127.0.0.1 — SEMANTICS.md); every failure is the async 'error' event,
* and an 'error' with no listener exits 1 like an unhandled EventEmitter
* 'error'. */
declare module "net" {
export interface Socket {
/* Whether the socket keeps the event loop alive (ref'd by default). */
ref(): void;
unref(): void;
readonly remoteAddress: string | undefined;
/* The peer's fields are cached at first read, like remoteAddress; the
* local ones are undefined while connecting and after close. */
readonly remotePort: number | undefined;
readonly remoteFamily: string | undefined;
readonly localAddress: string | undefined;
readonly localPort: number | undefined;
readonly localFamily: string | undefined;
readonly bytesRead: number;
readonly connecting: boolean;
readonly pending: boolean;
readonly readyState: "opening" | "open" | "readOnly" | "writeOnly" | "closed";
/* true once the fd is gone (destroy() or full close) — Node's flag. */
readonly destroyed: boolean;
/* the write half is open: no end() yet, no FIN sent, fd alive. */
readonly writable: boolean;
/* true until the read half is done (peer FIN / destroy). */
readonly readable: boolean;
/* every byte the write paths accepted (buffered included — Node
* counts those too; plaintext on TLS sockets). */
readonly bytesWritten: number;
/* write's callback runs once the data is flushed, with null; end's
* once the socket finishes. */
/* false when the bytes this write left unsent reach the 65536-byte
* high-water mark, as in Node; 'drain' fires when they are all sent. */
write(data: string | Uint8Array, callback?: (err?: Error | null) => void): boolean;
/* the bytes written and not yet sent */
readonly writableLength: number;
/* a write answered false and 'drain' has not fired yet */
readonly writableNeedDrain: boolean;
end(callback?: () => void): void;
end(data: string | Uint8Array, callback?: () => void): void;
destroy(): void;
/* Flow control: pause holds reads off (kernel/TCP backpressure is
* the buffer); resume flows — and discards without listeners, so
* 'end' stays reachable. Both chain, Node's shape. */
pause(): Socket;
resume(): Socket;
/* TCP_NODELAY on the live fd; missing means true. Chains. */
setNoDelay(noDelay?: boolean): Socket;
/* SO_KEEPALIVE with the initial delay in ms. Chains. */
setKeepAlive(enable?: boolean, initialDelay?: number): Socket;
/* end() now, destroy once the FIN actually flushed. */
destroySoon(): void;
/* An RST instead of a FIN; a connecting socket resets once it
* connects. Throws ERR_INVALID_HANDLE_TYPE on a TLS socket. */
resetAndDestroy(): Socket;
/* The local address, or {} while connecting and once destroyed. */
address(): AddressInfo | {};
/* setEncoding('utf8'): 'data' delivers strings — the IncomingMessage
* twin's contract. */
setEncoding(encoding: string): void;
/* socket→socket, and socket→response (the extended-CONNECT bridge
* leg: raw chunks become response body writes; EOF ends it). */
pipe(
destination: Socket | import("http").ServerResponse | import("http2").Http2ServerResponse,
): void;
/* The callback is a once('timeout') listener (removed again by 0). */
setTimeout(ms: number, callback?: () => void): void;
/* The paused-mode demux surface: once('readable') + read(1) +
* unshift — read answers exactly n buffered bytes or null. */
read(size?: number): Buffer | null;
unshift(chunk: Uint8Array): void;
/* secureConnect/secure/session are TLS-socket events declared on the
* shared socket surface (the lowering collapses TLSSocket onto this kind):
* the runtime gates on the transport, so a plain socket's
* registration never fires — Node's exact split. 'session' fires
* once with the serialized session (the received-ticket event). */
on(event: "data", listener: (chunk: Buffer) => void): void;
/* After setEncoding the chunk is a string. */
on(event: "data", listener: (chunk: string) => void): void;
on(
event:
| "end"
| "connect"
| "ready"
| "timeout"
| "drain"
| "readable"
| "finish"
| "secureConnect"
| "secure",
listener: () => void,
): void;
on(event: "close", listener: (hadError: boolean) => void): void;
on(event: "error", listener: (err: Error) => void): void;
on(event: "session", listener: (session: Buffer) => void): void;
/* The host name's resolution, before the connect. */
on(
event: "lookup",
listener: (err: Error | null, address: string, family: number, host: string) => void,
): void;
/* addListener IS on (Node aliases them) — the suite spells both. */
addListener(event: "data", listener: (chunk: Buffer) => void): void;
/* After setEncoding the chunk is a string. */
addListener(event: "data", listener: (chunk: string) => void): void;
addListener(
event:
| "end"
| "connect"
| "ready"
| "timeout"
| "drain"
| "readable"
| "finish"
| "secureConnect"
| "secure",
listener: () => void,
): void;
addListener(event: "close", listener: (hadError: boolean) => void): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(event: "session", listener: (session: Buffer) => void): void;
/* The host name's resolution, before the connect. */
addListener(
event: "lookup",
listener: (err: Error | null, address: string, family: number, host: string) => void,
): void;
once(event: "data", listener: (chunk: Buffer) => void): void;
/* After setEncoding the chunk is a string. */
once(event: "data", listener: (chunk: string) => void): void;
once(
event:
| "end"
| "connect"
| "ready"
| "timeout"
| "drain"
| "readable"
| "finish"
| "secureConnect"
| "secure",
listener: () => void,
): void;
once(event: "close", listener: (hadError: boolean) => void): void;
once(event: "error", listener: (err: Error) => void): void;
once(event: "session", listener: (session: Buffer) => void): void;
/* The host name's resolution, before the connect. */
once(
event: "lookup",
listener: (err: Error | null, address: string, family: number, host: string) => void,
): void;
}
export interface Server {
/* Whether the server keeps the event loop alive (ref'd by default). */
ref(): void;
unref(): void;
readonly listening: boolean;
/* Connections past this many are closed with a 'drop' event;
* undefined (the default) or null lifts the cap. */
maxConnections: number | undefined;
/* Node reads it only in cluster mode: a stored value here. */
dropMaxConnection: boolean | undefined;
/* cb(null, count) on the next tick. */
getConnections(callback: (error: Error | null, count: number) => void): Server;
/* Node answers the server itself (`return this` chaining). */
listen(port: number, callback?: () => void): Server;
/* The positional bind address (the options form's host in argument
* spelling). */
listen(port: number, host: string, callback?: () => void): Server;
/* A Unix-socket server; the socket file is removed when it closes. */
listen(path: string, callback?: () => void): Server;
/* The explicit-interface bind: host is an IP literal (absent = the
* host-less dual-stack any); ipv6Only sets IPV6_V6ONLY and reusePort
* requests kernel connection distribution where Node supports it. */
listen(
options: { port: number; host?: string; ipv6Only?: boolean; reusePort?: boolean },
callback?: () => void,
): Server;
close(callback?: () => void): void;
/* The bound AddressInfo (Node answers null before listen — this
* surface answers the record with port 0 there, the serverPort
* stance). */
address(): import("node:dgram").AddressInfo;
/* The demux route: hand an accepted socket to another server. */
emit(event: "connection", socket: Socket): boolean;
on(event: "connection" | "secureConnection", listener: (socket: Socket) => void): void;
/* tls and https servers: a handshake that failed */
on(
event: "tlsClientError",
listener: (err: Error, tlsSocket: import("tls").TLSSocket) => void,
): void;
on(event: "close" | "listening", listener: () => void): void;
on(event: "drop", listener: (data?: DropArgument) => void): void;
on(event: "timeout", listener: (socket: Socket) => void): void;
on(event: "error", listener: (err: Error) => void): void;
/* The WebSocket handover: fires INSTEAD of 'request' for
* Connection: upgrade requests, with the raw socket + head bytes;
* 'connect' is its twin for CONNECT requests (HTTP tunneling). */
on(
event: "upgrade" | "connect",
listener: (req: import("http").IncomingMessage, socket: Socket, head: Buffer) => void,
): void;
/* http.createServer(handler)'s event twin (a no-parser net server
* never fires it, like Node). */
on(
event: "request" | "checkContinue" | "checkExpectation",
listener: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => void,
): void;
/* addListener IS on (Node aliases them) — the suite spells both. */
addListener(event: "connection" | "secureConnection", listener: (socket: Socket) => void): void;
/* tls and https servers: a handshake that failed */
addListener(
event: "tlsClientError",
listener: (err: Error, tlsSocket: import("tls").TLSSocket) => void,
): void;
addListener(event: "close" | "listening", listener: () => void): void;
addListener(event: "drop", listener: (data?: DropArgument) => void): void;
addListener(event: "timeout", listener: (socket: Socket) => void): void;
addListener(event: "error", listener: (err: Error) => void): void;
addListener(
event: "upgrade" | "connect",
listener: (req: import("http").IncomingMessage, socket: Socket, head: Buffer) => void,
): void;
addListener(
event: "request" | "checkContinue" | "checkExpectation",
listener: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => void,
): void;
once(event: "connection" | "secureConnection", listener: (socket: Socket) => void): void;
/* tls and https servers: a handshake that failed */
once(
event: "tlsClientError",
listener: (err: Error, tlsSocket: import("tls").TLSSocket) => void,
): void;
once(event: "close" | "listening", listener: () => void): void;
once(event: "drop", listener: (data?: DropArgument) => void): void;
once(event: "timeout", listener: (socket: Socket) => void): void;
once(event: "error", listener: (err: Error) => void): void;
once(
event: "upgrade" | "connect",
listener: (req: import("http").IncomingMessage, socket: Socket, head: Buffer) => void,
): void;
once(
event: "request" | "checkContinue" | "checkExpectation",
listener: (req: import("http").IncomingMessage, res: import("http").ServerResponse) => void,
): void;
}
/* The 'drop' payload: the turned-away connection's addresses. */
export interface DropArgument {
localAddress?: string;
localPort?: number;
localFamily?: string;
remoteAddress?: string;
remotePort?: number;
remoteFamily?: string;
}
export type AddressInfo = import("node:dgram").AddressInfo;
export type IPVersion = "ipv4" | "ipv6";
export interface SocketAddressInitOptions {
address?: string;
family?: IPVersion;
flowlabel?: number;
port?: number;
}
/* A native handle (scr_net.c); the getters read its parsed address. */
export class SocketAddress {
constructor(options?: SocketAddressInitOptions);
readonly address: string;
readonly family: IPVersion;
readonly port: number;
readonly flowlabel: number;
toJSON(): { address: string; port: number; family: IPVersion; flowlabel: number };
/* undefined when the input is not "<ip>[:<port>]" */
static parse(input: string): SocketAddress | undefined;
static isSocketAddress(value: unknown): value is SocketAddress;
}
/* Address, range and subnet rules; check() matches IPv4 addresses
* against IPv6 rules through their IPv4-mapped form, as Node does. */
export class BlockList {
constructor();
readonly rules: readonly string[];
readonly size: number;
addAddress(address: string | SocketAddress, type?: IPVersion): void;
addAddresses(addresses: readonly (string | SocketAddress)[], type?: IPVersion): void;
addRange(start: string | SocketAddress, end: string | SocketAddress, type?: IPVersion): void;
addSubnet(net: string | SocketAddress, prefix: number, type?: IPVersion): void;
addCIDR(cidr: string): void;
addCIDRs(cidrs: readonly string[]): void;
removeAddress(address: string | SocketAddress, type?: IPVersion): void;
removeRange(start: string | SocketAddress, end: string | SocketAddress, type?: IPVersion): void;
removeSubnet(net: string | SocketAddress, prefix: number, type?: IPVersion): void;
removeCIDR(cidr: string): void;
clear(): void;
check(address: string | SocketAddress, type?: IPVersion): boolean;
toJSON(): string[];
fromJSON(data: string | readonly string[]): void;
static isBlockList(value: unknown): value is BlockList;
static readonly PRIVATE_RANGES: readonly string[];
}
/* Node's IPv4Reg and IPv6Reg tests: 4, 6, or 0 for isIP. */
export function isIP(input: string): number;
export function isIPv4(input: string): boolean;
export function isIPv6(input: string): boolean;
/* The Socket VALUE — the `x instanceof net.Socket` narrowing target
* (the h2 compat 'connect' listener's test). Constructing bare sockets
* has no lowering; the construct signature exists for instanceof. */
export const Socket: abstract new () => Socket;
export function createServer(connectionListener?: (socket: Socket) => void): Server;
export function connect(port: number, host?: string, connectListener?: () => void): Socket;
export function createConnection(
port: number,
host?: string,
connectListener?: () => void,
): Socket;
/* The caller-resolver dial (@types/node's net.LookupFunction): the
* runtime invokes it as Node's autoSelectFamily dial does (options
* { hints, all: true }, so the callback answers an address list) and
* dials the answered addresses in order. */
export type LookupFunction = (
hostname: string,
options: import("node:dns").LookupOptions,
callback: (
err: NodeJS.ErrnoException | null,
address: string | import("node:dns").LookupAddress[],
family?: number,
) => void,
) => void;
export function connect(
options: {
port: number;
host?: string;
autoSelectFamily?: boolean;
lookup?: LookupFunction;
},
connectListener?: () => void,
): Socket;
export function createConnection(
options: {
port: number;
host?: string;
autoSelectFamily?: boolean;
lookup?: LookupFunction;
},
connectListener?: () => void,
): Socket;
/* The happy-eyeballs attempt budget (Node's process-wide knob; the
* autoSelectFamily dial consults it): one runtime int, default 250ms
* like Node's. */
export function getDefaultAutoSelectFamilyAttemptTimeout(): number;
export function setDefaultAutoSelectFamilyAttemptTimeout(value: number): void;
}
declare module "node:net" {
export * from "net";
}
+288
View File
@@ -0,0 +1,288 @@
/* node:os — the slice a CLI needs: platform() (same implementation as
* process.platform), homedir(), tmpdir() (Node's env cascade), EOL
* (always "\n" — POSIX pinned, like path.sep), and networkInterfaces()
* (getifaddrs(3); the interface shapes mirror @types/node's exactly so
* both type worlds map to the same IR structure). */
declare module "os" {
export function platform(): string;
export function homedir(): string;
export function tmpdir(): string;
/* uname(2)'s release field — Node's own implementation. */
export function release(): string;
/* uname(2)'s sysname field ("Darwin", "Linux") — Node's os.type(). */
export function type(): string;
/* Total system memory in bytes (sysctl hw.memsize / sysconf). */
export function totalmem(): number;
export function availableParallelism(): number;
/* The passwd-entry snapshot (uv_os_get_passwd): shell is `string |
* null` to match @types/node (POSIX always answers the string arm);
* homedir is pw_dir — NOT os.homedir()'s $HOME-first cascade. The type
* is interned explicitly in type-mapper.ts (the AddressInfo pattern — this
* concrete form and @types/node's UserInfo<string> both), and the call
* assembles field-by-field in lowerOsUserInfoCall. */
export interface UserInfo {
username: string;
uid: number;
gid: number;
shell: string | null;
homedir: string;
}
export function userInfo(): UserInfo;
/* The TARGET platform's line terminator (a compile-time constant:
* "\r\n" under a win32 triple, "\n" everywhere else). */
export const EOL: "\r\n" | "\n";
export interface NetworkInterfaceBase {
address: string;
netmask: string;
mac: string;
internal: boolean;
cidr: string | null;
scopeid?: number;
}
export interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase {
family: "IPv4";
}
export interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase {
family: "IPv6";
scopeid: number;
}
export type NetworkInterfaceInfo = NetworkInterfaceInfoIPv4 | NetworkInterfaceInfoIPv6;
export function networkInterfaces(): { [name: string]: NetworkInterfaceInfo[] | undefined };
/* Host facts, libuv's answers: model/speed/times per logical CPU, the
* host name, the 1/5/15-minute load averages, uptime in seconds, free
* memory in bytes, process.arch, uname's machine and version fields,
* the byte order, and a process's scheduling priority (an omitted pid
* is the current process). Shapes mirror @types/node's. */
export interface CpuInfo {
model: string;
speed: number;
times: {
user: number;
nice: number;
sys: number;
idle: number;
irq: number;
};
}
export function cpus(): CpuInfo[];
export function hostname(): string;
export function loadavg(): number[];
export function uptime(): number;
export function freemem(): number;
export function arch(): string;
export function machine(): string;
export function version(): string;
export function endianness(): "BE" | "LE";
export function getPriority(pid?: number): number;
export function setPriority(priority: number): void;
export function setPriority(pid: number, priority: number): void;
/* The TARGET platform's null device ("\\\\.\\nul" under a win32 triple). */
export const devNull: string;
/* The platform's constants: null-prototype objects with read-only
* members, `signals` frozen (Node's internalBinding('constants').os). */
export type SignalConstants = {
[
key in
| "SIGABRT"
| "SIGALRM"
| "SIGBUS"
| "SIGCHLD"
| "SIGCONT"
| "SIGFPE"
| "SIGHUP"
| "SIGILL"
| "SIGINT"
| "SIGIO"
| "SIGIOT"
| "SIGKILL"
| "SIGPIPE"
| "SIGPOLL"
| "SIGPROF"
| "SIGPWR"
| "SIGQUIT"
| "SIGSEGV"
| "SIGSTKFLT"
| "SIGSTOP"
| "SIGSYS"
| "SIGTERM"
| "SIGTRAP"
| "SIGTSTP"
| "SIGTTIN"
| "SIGTTOU"
| "SIGUNUSED"
| "SIGURG"
| "SIGUSR1"
| "SIGUSR2"
| "SIGVTALRM"
| "SIGWINCH"
| "SIGXCPU"
| "SIGXFSZ"
| "SIGBREAK"
| "SIGLOST"
| "SIGINFO"
]: number;
};
export namespace constants {
const UV_UDP_REUSEADDR: number;
namespace signals {}
const signals: SignalConstants;
namespace errno {
const E2BIG: number;
const EACCES: number;
const EADDRINUSE: number;
const EADDRNOTAVAIL: number;
const EAFNOSUPPORT: number;
const EAGAIN: number;
const EALREADY: number;
const EBADF: number;
const EBADMSG: number;
const EBUSY: number;
const ECANCELED: number;
const ECHILD: number;
const ECONNABORTED: number;
const ECONNREFUSED: number;
const ECONNRESET: number;
const EDEADLK: number;
const EDESTADDRREQ: number;
const EDOM: number;
const EDQUOT: number;
const EEXIST: number;
const EFAULT: number;
const EFBIG: number;
const EHOSTUNREACH: number;
const EIDRM: number;
const EILSEQ: number;
const EINPROGRESS: number;
const EINTR: number;
const EINVAL: number;
const EIO: number;
const EISCONN: number;
const EISDIR: number;
const ELOOP: number;
const EMFILE: number;
const EMLINK: number;
const EMSGSIZE: number;
const EMULTIHOP: number;
const ENAMETOOLONG: number;
const ENETDOWN: number;
const ENETRESET: number;
const ENETUNREACH: number;
const ENFILE: number;
const ENOBUFS: number;
const ENODATA: number;
const ENODEV: number;
const ENOENT: number;
const ENOEXEC: number;
const ENOLCK: number;
const ENOLINK: number;
const ENOMEM: number;
const ENOMSG: number;
const ENOPROTOOPT: number;
const ENOSPC: number;
const ENOSR: number;
const ENOSTR: number;
const ENOSYS: number;
const ENOTCONN: number;
const ENOTDIR: number;
const ENOTEMPTY: number;
const ENOTSOCK: number;
const ENOTSUP: number;
const ENOTTY: number;
const ENXIO: number;
const EOPNOTSUPP: number;
const EOVERFLOW: number;
const EPERM: number;
const EPIPE: number;
const EPROTO: number;
const EPROTONOSUPPORT: number;
const EPROTOTYPE: number;
const ERANGE: number;
const EROFS: number;
const ESPIPE: number;
const ESRCH: number;
const ESTALE: number;
const ETIME: number;
const ETIMEDOUT: number;
const ETXTBSY: number;
const EWOULDBLOCK: number;
const EXDEV: number;
const WSAEINTR: number;
const WSAEBADF: number;
const WSAEACCES: number;
const WSAEFAULT: number;
const WSAEINVAL: number;
const WSAEMFILE: number;
const WSAEWOULDBLOCK: number;
const WSAEINPROGRESS: number;
const WSAEALREADY: number;
const WSAENOTSOCK: number;
const WSAEDESTADDRREQ: number;
const WSAEMSGSIZE: number;
const WSAEPROTOTYPE: number;
const WSAENOPROTOOPT: number;
const WSAEPROTONOSUPPORT: number;
const WSAESOCKTNOSUPPORT: number;
const WSAEOPNOTSUPP: number;
const WSAEPFNOSUPPORT: number;
const WSAEAFNOSUPPORT: number;
const WSAEADDRINUSE: number;
const WSAEADDRNOTAVAIL: number;
const WSAENETDOWN: number;
const WSAENETUNREACH: number;
const WSAENETRESET: number;
const WSAECONNABORTED: number;
const WSAECONNRESET: number;
const WSAENOBUFS: number;
const WSAEISCONN: number;
const WSAENOTCONN: number;
const WSAESHUTDOWN: number;
const WSAETOOMANYREFS: number;
const WSAETIMEDOUT: number;
const WSAECONNREFUSED: number;
const WSAELOOP: number;
const WSAENAMETOOLONG: number;
const WSAEHOSTDOWN: number;
const WSAEHOSTUNREACH: number;
const WSAENOTEMPTY: number;
const WSAEPROCLIM: number;
const WSAEUSERS: number;
const WSAEDQUOT: number;
const WSAESTALE: number;
const WSAEREMOTE: number;
const WSASYSNOTREADY: number;
const WSAVERNOTSUPPORTED: number;
const WSANOTINITIALISED: number;
const WSAEDISCON: number;
const WSAENOMORE: number;
const WSAECANCELLED: number;
const WSAEINVALIDPROCTABLE: number;
const WSAEINVALIDPROVIDER: number;
const WSAEPROVIDERFAILEDINIT: number;
const WSASYSCALLFAILURE: number;
const WSASERVICE_NOT_FOUND: number;
const WSATYPE_NOT_FOUND: number;
const WSA_E_NO_MORE: number;
const WSA_E_CANCELLED: number;
const WSAEREFUSED: number;
}
namespace dlopen {
const RTLD_LAZY: number;
const RTLD_NOW: number;
const RTLD_GLOBAL: number;
const RTLD_LOCAL: number;
const RTLD_DEEPBIND: number;
}
namespace priority {
const PRIORITY_LOW: number;
const PRIORITY_BELOW_NORMAL: number;
const PRIORITY_NORMAL: number;
const PRIORITY_ABOVE_NORMAL: number;
const PRIORITY_HIGH: number;
const PRIORITY_HIGHEST: number;
}
}
}
declare module "node:os" {
export * from "os";
}
+22
View File
@@ -0,0 +1,22 @@
/// <reference path="./path.d.ts" />
declare module "path/posix" {
export function join(...paths: string[]): string;
export function resolve(...paths: string[]): string;
export function normalize(path: string): string;
export function dirname(path: string): string;
export function basename(path: string, suffix?: string): string;
export function extname(path: string): string;
export function isAbsolute(path: string): boolean;
export function relative(from: string, to: string): string;
export function toNamespacedPath(path: string): string;
export function matchesGlob(path: string, pattern: string): boolean;
export function parse(path: string): import("path").ParsedPath;
export function format(pathObject: import("path").FormatInputPathObject): string;
export const sep: "/";
export const delimiter: ":";
}
declare module "node:path/posix" {
export * from "path/posix";
}
+22
View File
@@ -0,0 +1,22 @@
/// <reference path="./path.d.ts" />
declare module "path/win32" {
export function join(...paths: string[]): string;
export function resolve(...paths: string[]): string;
export function normalize(path: string): string;
export function dirname(path: string): string;
export function basename(path: string, suffix?: string): string;
export function extname(path: string): string;
export function isAbsolute(path: string): boolean;
export function relative(from: string, to: string): string;
export function toNamespacedPath(path: string): string;
export function matchesGlob(path: string, pattern: string): boolean;
export function parse(path: string): import("path").ParsedPath;
export function format(pathObject: import("path").FormatInputPathObject): string;
export const sep: "\\";
export const delimiter: ";";
}
declare module "node:path/win32" {
export * from "path/win32";
}
+55
View File
@@ -0,0 +1,55 @@
/// <reference path="./path-posix.d.ts" />
/// <reference path="./path-win32.d.ts" />
/* node:path — the TARGET platform's implementation (Node's rule): posix
* on posix triples, path.win32 under a win32 triple, with the posix and
* win32 namespaces answering their own platform anywhere. Every function
* is a pure string algorithm matching Node's implementations
* exactly; join/resolve are variadic like Node's. */
declare module "path" {
export function join(...paths: string[]): string;
export function resolve(...paths: string[]): string;
export function normalize(path: string): string;
export function dirname(path: string): string;
export function basename(path: string, suffix?: string): string;
export function extname(path: string): string;
export function isAbsolute(path: string): boolean;
export function relative(from: string, to: string): string;
export function toNamespacedPath(path: string): string;
/* matchesGlob() is Node's glob matcher: brace expansion, extglobs, POSIX
* classes and the ** and dot rules. */
export function matchesGlob(path: string, pattern: string): boolean;
/* parse() splits a path into its root, directory, base, extension and
* name; format() joins those fields back (Node's `||` defaults). */
export interface ParsedPath {
root: string;
dir: string;
base: string;
ext: string;
name: string;
}
export interface FormatInputPathObject {
root?: string | undefined;
dir?: string | undefined;
base?: string | undefined;
ext?: string | undefined;
name?: string | undefined;
}
export function parse(path: string): ParsedPath;
export function format(pathObject: FormatInputPathObject): string;
/* The union @types/node declares: the bare module answers the TARGET
* platform's value (a compile-time constant — "\\"/";" under a win32
* triple, "/"/":" everywhere else). */
export const sep: "\\" | "/";
export const delimiter: ";" | ":";
/* The platform-specific namespaces (real Node submodules too —
* "node:path/posix" resolves). Each carries the FULL surface and
* answers ITS platform's rules on any target, Node's own contract;
* the bare module IS the target platform's implementation. */
export const posix: typeof import("path/posix");
export const win32: typeof import("path/win32");
}
declare module "node:path" {
export * from "path";
}
+11
View File
@@ -0,0 +1,11 @@
/* Node's process module default export is the global process object. These
* declaration aliases let the ESM spelling typecheck against the same
* deliberately narrow fallback surface when @types/node is absent. */
declare module "process" {
export = process;
}
declare module "node:process" {
import process = require("process");
export = process;
}
+18
View File
@@ -0,0 +1,18 @@
/* node:punycode (deprecated, DEP0040) — punycode.js 2.1.0: decode and
* toUnicode throw its RangeErrors on malformed input; ucs2 converts
* between strings and UTF-16 code point arrays. */
declare module "punycode" {
export function decode(string: string): string;
export function encode(string: string): string;
export function toUnicode(domain: string): string;
export function toASCII(domain: string): string;
export namespace ucs2 {
function decode(string: string): number[];
function encode(codePoints: readonly number[]): string;
}
export const version: string;
}
declare module "node:punycode" {
export * from "punycode";
}
@@ -0,0 +1,55 @@
/* node:querystring — Node's legacy query-string codec (NOT
* URLSearchParams: '+' means space on the parse side and escape encodes
* spaces as %20). parse answers the null-prototype dictionary as a pure
* index-signature record (repeated keys become string[] buckets;
* @types/node's Dict adds an undefined arm the lowering tolerates);
* stringify serializes string/number/boolean values and arrays of those
* (Node's rules: arrays expand to repeated keys, null/undefined and
* anything else serialize as the empty value). The maxKeys option lowers
* (0 removes the cap, Node's rule); the custom encoder/decoder options
* typecheck under the options-record stance and fence by name at the
* call. decode/encode are Node's own aliases of parse/stringify. */
declare module "querystring" {
export interface ParseOptions {
maxKeys?: number;
decodeURIComponent?: (str: string) => string;
[option: string]: unknown;
}
export interface StringifyOptions {
encodeURIComponent?: (str: string) => string;
[option: string]: unknown;
}
export interface ParsedUrlQuery {
[key: string]: string | string[] | undefined;
}
export interface ParsedUrlQueryInput {
[key: string]:
| string
| number
| boolean
| bigint
| ReadonlyArray<string | number | boolean | bigint>
| null
| undefined;
}
export function parse(
str: string,
sep?: string | null,
eq?: string | null,
options?: ParseOptions,
): ParsedUrlQuery;
export function stringify(
obj?: ParsedUrlQueryInput,
sep?: string | null,
eq?: string | null,
options?: StringifyOptions,
): string;
export const decode: typeof parse;
export const encode: typeof stringify;
export function escape(str: string): string;
export function unescape(str: string): string;
}
declare module "node:querystring" {
export * from "querystring";
}
@@ -0,0 +1,21 @@
declare module "stream/consumers" {
/* The promise consumers over a readable: accumulate every chunk and
* settle — text (the utf8 decode), json (the text through JSON.parse:
* `unknown`, validated with a checked cast; malformed input rejects
* with the parse's SyntaxError), buffer (the concatenated bytes;
* string chunks contribute their utf8 bytes, Node's Blob rule).
* Stream errors reject; an early close rejects with
* ERR_STREAM_PREMATURE_CLOSE. arrayBuffer answers an ArrayBuffer over
* the bytes; blob fences per site. */
function text(stream: unknown): Promise<string>;
function json(stream: unknown): Promise<unknown>;
function buffer(stream: unknown): Promise<Buffer>;
function arrayBuffer(stream: unknown): Promise<ArrayBuffer>;
function blob(stream: unknown): Promise<unknown>;
export { arrayBuffer, blob, buffer, json, text };
}
declare module "node:stream/consumers" {
import streamConsumers = require("stream/consumers");
export = streamConsumers;
}
@@ -0,0 +1,28 @@
/// <reference path="./stream.d.ts" />
declare module "stream/promises" {
/* The promise forms of finished/pipeline: a void promise the stream's
* terminal point settles (rejected with the error, or
* ERR_STREAM_PREMATURE_CLOSE on an early close). Stream arguments are
* the lowered surface — iterables/generators/functions fence per site.
* pipeline's trailing { signal, end } object and finished's options
* (readable, writable, error, cleanup, signal) are supported. A last
* stage that is an async function resolves the promise with its value. */
function pipeline<T extends unknown[]>(...streams: T): import("stream").PipelinePromise<T>;
function finished(
stream: unknown,
options?: {
readable?: boolean;
writable?: boolean;
error?: boolean;
cleanup?: boolean;
signal?: AbortSignal;
} | null,
): Promise<void>;
export { pipeline, finished };
}
declare module "node:stream/promises" {
import streamPromises = require("stream/promises");
export = streamPromises;
}
+17
View File
@@ -0,0 +1,17 @@
/* node:stream/web — the module exports the web stream globals themselves
* (require("stream/web").ReadableStream === globalThis.ReadableStream).
* ReadableStream is the implemented class; its reader and controller are
* exported as types. */
declare module "stream/web" {
export const ReadableStream: typeof globalThis.ReadableStream;
export type ReadableStream<T = unknown> = globalThis.ReadableStream<T>;
export type ReadableStreamDefaultReader<T = unknown> = globalThis.ReadableStreamDefaultReader<T>;
export type ReadableStreamDefaultController<T = unknown> =
globalThis.ReadableStreamDefaultController<T>;
export type UnderlyingSource<T = unknown> = globalThis.UnderlyingSource<T>;
export type QueuingStrategy<T = unknown> = globalThis.QueuingStrategy<T>;
}
declare module "node:stream/web" {
export * from "stream/web";
}
+644
View File
@@ -0,0 +1,644 @@
/// <reference path="./events.d.ts" />
/* node:stream — the static stream classes (runtime-provided, the
* EventEmitter-hierarchy precedent). Phase 1 is the OPTIONS-OBJECT
* constructor surface: `new Readable({ read() {} })`, `new Writable({
* write(chunk, enc, cb) {} })`, Duplex/Transform/PassThrough, push/read,
* flowing vs paused, write/end backpressure + 'drain', pipe/unpipe, and
* destroy — with Node's event orderings. Chunks are BYTES (Buffer), with
* strings converted at push/write like Node, and any value on an
* object-mode side (objectMode, readableObjectMode, writableObjectMode —
* the object-mode constructor overloads come first). The runtime-fired
* events carry per-class FORCED argument tuples ('data' is one chunk,
* 'error' one Error, 'pipe'/'unpipe' one Readable, the rest empty) — the
* overloads below hand tsc the same contract so unannotated listener
* parameters contextually type in .js sources. */
declare module "stream" {
import { EventEmitter } from "events";
interface ReadableOptions {
highWaterMark?: number;
encoding?: string;
objectMode?: boolean;
read?(this: Readable, size: number): void;
destroy?(this: Readable, error: Error | null, callback: (error?: Error | null) => void): void;
construct?(this: Readable, callback: (error?: Error | null) => void): void;
autoDestroy?: boolean;
emitClose?: boolean;
captureRejections?: boolean;
defaultEncoding?: string;
signal?: AbortSignal;
}
interface WritableOptions {
highWaterMark?: number;
decodeStrings?: boolean;
defaultEncoding?: string;
objectMode?: boolean;
write?(
this: Writable,
chunk: Buffer,
encoding: string,
callback: (error?: Error | null) => void,
): void;
writev?(
this: Writable,
chunks: Array<{ chunk: any; encoding: string }>,
callback: (error?: Error | null) => void,
): void;
final?(this: Writable, callback: (error?: Error | null) => void): void;
destroy?(this: Writable, error: Error | null, callback: (error?: Error | null) => void): void;
construct?(this: Writable, callback: (error?: Error | null) => void): void;
autoDestroy?: boolean;
emitClose?: boolean;
captureRejections?: boolean;
signal?: AbortSignal;
}
interface DuplexOptions {
highWaterMark?: number;
readableHighWaterMark?: number;
writableHighWaterMark?: number;
encoding?: string;
decodeStrings?: boolean;
objectMode?: boolean;
readableObjectMode?: boolean;
writableObjectMode?: boolean;
allowHalfOpen?: boolean;
read?(this: Duplex, size: number): void;
write?(
this: Duplex,
chunk: Buffer,
encoding: string,
callback: (error?: Error | null) => void,
): void;
final?(this: Duplex, callback: (error?: Error | null) => void): void;
destroy?(this: Duplex, error: Error | null, callback: (error?: Error | null) => void): void;
construct?(this: Duplex, callback: (error?: Error | null) => void): void;
autoDestroy?: boolean;
emitClose?: boolean;
captureRejections?: boolean;
readable?: boolean;
writable?: boolean;
defaultEncoding?: string;
writev?(
this: Duplex,
chunks: Array<{ chunk: any; encoding: string }>,
callback: (error?: Error | null) => void,
): void;
signal?: AbortSignal;
}
interface TransformOptions {
highWaterMark?: number;
readableHighWaterMark?: number;
writableHighWaterMark?: number;
encoding?: string;
decodeStrings?: boolean;
objectMode?: boolean;
readableObjectMode?: boolean;
writableObjectMode?: boolean;
allowHalfOpen?: boolean;
transform?(
this: Transform,
chunk: Buffer,
encoding: string,
callback: (error?: Error | null, data?: Buffer | string) => void,
): void;
flush?(this: Transform, callback: (error?: Error | null, data?: Buffer | string) => void): void;
destroy?(this: Transform, error: Error | null, callback: (error?: Error | null) => void): void;
construct?(this: Transform, callback: (error?: Error | null) => void): void;
read?(this: Transform, size: number): void;
write?(
this: Transform,
chunk: Buffer,
encoding: string,
callback: (error?: Error | null) => void,
): void;
final?(this: Transform, callback: (error?: Error | null) => void): void;
writev?(this: Transform, chunks: unknown[], callback: (error?: Error | null) => void): void;
autoDestroy?: boolean;
emitClose?: boolean;
captureRejections?: boolean;
readable?: boolean;
writable?: boolean;
defaultEncoding?: string;
signal?: AbortSignal;
}
/* Object-mode options (objectMode: true, or a Duplex's or Transform's
* readableObjectMode / writableObjectMode): chunks and completion data
* are any values, and an object-mode write's encoding argument reaches
* write/transform as passed (undefined when absent, null when a
* callback took its place). The constructors take these before the
* byte-mode options, so a byte-mode stream's callbacks keep Buffer
* chunks. */
type ObjectModeEncoding = string | null | undefined;
type ObjectModeFlag =
| { objectMode: true }
| { readableObjectMode: true }
| { writableObjectMode: true };
interface ObjectWritableOptions extends Omit<WritableOptions, "objectMode" | "write"> {
objectMode: true;
write?(
this: Writable,
chunk: any,
encoding: ObjectModeEncoding,
callback: (error?: Error | null) => void,
): void;
}
type ObjectDuplexOptions = Omit<DuplexOptions, "write"> & {
write?(
this: Duplex,
chunk: any,
encoding: ObjectModeEncoding,
callback: (error?: Error | null) => void,
): void;
} & ObjectModeFlag;
type ObjectTransformOptions = Omit<TransformOptions, "transform" | "flush" | "write"> & {
transform?(
this: Transform,
chunk: any,
encoding: ObjectModeEncoding,
callback: (error?: Error | null, data?: any) => void,
): void;
flush?(this: Transform, callback: (error?: Error | null, data?: any) => void): void;
write?(
this: Transform,
chunk: any,
encoding: ObjectModeEncoding,
callback: (error?: Error | null) => void,
): void;
} & ObjectModeFlag;
/* decodeStrings: false — a string write reaches write/transform as the
* string with its encoding (Buffers keep 'buffer'). */
interface StringWritableOptions extends Omit<WritableOptions, "decodeStrings" | "write"> {
decodeStrings: false;
write?(
this: Writable,
chunk: string | Buffer,
encoding: string,
callback: (error?: Error | null) => void,
): void;
}
type StringDuplexOptions = Omit<DuplexOptions, "decodeStrings" | "write"> & {
decodeStrings: false;
write?(
this: Duplex,
chunk: string | Buffer,
encoding: string,
callback: (error?: Error | null) => void,
): void;
};
type StringTransformOptions = Omit<TransformOptions, "decodeStrings" | "transform"> & {
decodeStrings: false;
transform?(
this: Transform,
chunk: string | Buffer,
encoding: string,
callback: (error?: Error | null, data?: Buffer | string) => void,
): void;
};
/* The operators' options: concurrency and highWaterMark bound map's
* in-flight callbacks and queued results. */
interface ArrayOptions {
concurrency?: number;
highWaterMark?: number;
signal?: AbortSignal;
}
class Readable extends EventEmitter {
constructor(opts?: ReadableOptions);
/* The underscore-method surface (@types/node declares these on the
* classes; assigning them post-construction shadows the prototype
* method and the machinery calls through the assignment — lowered
* onto the option-callback slots). */
_read(size: number): void;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
[Symbol.asyncIterator](): AsyncIterableIterator<any>;
iterator(options?: { destroyOnReturn?: boolean }): AsyncIterableIterator<any>;
/* compose(this, stage), destroyed when options.signal aborts. */
compose(stage: ComposeStage, options?: { signal: AbortSignal }): Duplex;
push(chunk: Buffer | string | null, encoding?: string): boolean;
/* An object-mode stream's values. */
push(chunk: any, encoding?: string): boolean;
unshift(chunk: Buffer | string, encoding?: string): void;
unshift(chunk: any, encoding?: string): void;
/* A Buffer, a string once encoded, an object-mode value, or null (as
* @types/node types it). */
read(size?: number): any;
pause(): this;
resume(): this;
isPaused(): boolean;
setEncoding(encoding: string): this;
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean }): T;
unpipe(destination?: NodeJS.WritableStream): this;
destroy(error?: Error): this;
readonly readable: boolean;
readonly readableEnded: boolean;
readonly readableFlowing: boolean | null;
readonly readableLength: number;
readonly readableHighWaterMark: number;
readonly readableObjectMode: boolean;
readonly closed: boolean;
readonly destroyed: boolean;
readonly errored: Error | null;
static from(iterable: unknown, options?: ReadableOptions): Readable;
/* A Readable over a web ReadableStream's reader. */
static fromWeb(
readableStream: globalThis.ReadableStream,
options?: {
encoding?: string;
highWaterMark?: number;
objectMode?: boolean;
signal?: AbortSignal;
},
): Readable;
/* The Readable operators: chunks are strings or Buffers, map and
* flatMap callbacks return strings or Buffers (flatMap: arrays of
* them, or strings), and callbacks that declare the options argument
* are refused. */
map(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => any,
options?: ArrayOptions,
): Readable;
filter(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>,
options?: ArrayOptions,
): Readable;
forEach(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => void | Promise<void>,
options?: ArrayOptions,
): Promise<void>;
toArray(options?: Pick<ArrayOptions, "signal">): Promise<any[]>;
some(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>,
options?: ArrayOptions,
): Promise<boolean>;
find(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>,
options?: ArrayOptions,
): Promise<any>;
every(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>,
options?: ArrayOptions,
): Promise<boolean>;
flatMap(
fn: (data: any, options?: Pick<ArrayOptions, "signal">) => any,
options?: ArrayOptions,
): Readable;
drop(limit: number, options?: Pick<ArrayOptions, "signal">): Readable;
take(limit: number, options?: Pick<ArrayOptions, "signal">): Readable;
reduce<T = any>(
fn: (previous: any, data: any, options?: Pick<ArrayOptions, "signal">) => T,
initial?: undefined,
options?: Pick<ArrayOptions, "signal">,
): Promise<T>;
reduce<T = any>(
fn: (previous: T, data: any, options?: Pick<ArrayOptions, "signal">) => T,
initial: T,
options?: Pick<ArrayOptions, "signal">,
): Promise<T>;
on(event: "data", listener: (chunk: any) => void): this;
on(event: "end" | "close" | "readable" | "pause" | "resume", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
once(event: "data", listener: (chunk: any) => void): this;
once(event: "end" | "close" | "readable" | "pause" | "resume", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
addListener(event: "data", listener: (chunk: any) => void): this;
addListener(
event: "end" | "close" | "readable" | "pause" | "resume",
listener: () => void,
): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "data", listener: (chunk: any) => void): this;
prependListener(
event: "end" | "close" | "readable" | "pause" | "resume",
listener: () => void,
): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "data", listener: (chunk: any) => void): this;
prependOnceListener(
event: "end" | "close" | "readable" | "pause" | "resume",
listener: () => void,
): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
off(event: "data", listener: (chunk: any) => void): this;
off(event: "end" | "close" | "readable" | "pause" | "resume", listener: () => void): this;
off(event: "error", listener: (err: Error) => void): this;
off(event: string, listener: (...args: any[]) => void): this;
removeListener(event: "data", listener: (chunk: any) => void): this;
removeListener(
event: "end" | "close" | "readable" | "pause" | "resume",
listener: () => void,
): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
}
class Writable extends EventEmitter {
constructor(opts: ObjectWritableOptions);
constructor(opts: StringWritableOptions);
constructor(opts?: WritableOptions);
/* The underscore-method surface (see Readable). */
_write(chunk: any, encoding: string, callback: (error?: Error | null) => void): void;
_writev(
chunks: Array<{ chunk: any; encoding: string }>,
callback: (error?: Error | null) => void,
): void;
_final(callback: (error?: Error | null) => void): void;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
write(chunk: Buffer | string, callback?: (error?: Error | null) => void): boolean;
write(
chunk: Buffer | string,
encoding: string,
callback?: (error?: Error | null) => void,
): boolean;
/* An object-mode stream's values (the encoding argument reaches
* _write as passed). */
write(chunk: any, callback?: (error?: Error | null) => void): boolean;
write(
chunk: any,
encoding: ObjectModeEncoding,
callback?: (error?: Error | null) => void,
): boolean;
end(callback?: () => void): this;
end(chunk: Buffer | string, callback?: () => void): this;
end(chunk: Buffer | string, encoding: string, callback?: () => void): this;
end(chunk: any, callback?: () => void): this;
end(chunk: any, encoding: ObjectModeEncoding, callback?: () => void): this;
cork(): void;
uncork(): void;
setDefaultEncoding(encoding: string): this;
destroy(error?: Error): this;
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableLength: number;
readonly writableHighWaterMark: number;
readonly writableObjectMode: boolean;
readonly writableNeedDrain: boolean;
readonly writableCorked: number;
readonly closed: boolean;
readonly destroyed: boolean;
readonly errored: Error | null;
on(event: "drain" | "finish" | "close", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
once(event: "drain" | "finish" | "close", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
addListener(event: "drain" | "finish" | "close", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
addListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "drain" | "finish" | "close", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "drain" | "finish" | "close", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
off(event: "drain" | "finish" | "close", listener: () => void): this;
off(event: "error", listener: (err: Error) => void): this;
off(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
off(event: string, listener: (...args: any[]) => void): this;
removeListener(event: "drain" | "finish" | "close", listener: () => void): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
}
/* Duplex is Readable + Writable in one object. TS single inheritance
* mirrors @types/node: extends Readable, the writable half declared
* again. The lowering treats both halves as first-class. */
class Duplex extends Readable {
/* Duplex.from: an async generator function, an iterable, a string or
* a stream (duplexify.js). */
static from(body: unknown): Duplex;
constructor(opts: ObjectDuplexOptions);
constructor(opts: StringDuplexOptions);
constructor(opts?: DuplexOptions);
/* The underscore-method surface (see Readable). */
_write(chunk: any, encoding: string, callback: (error?: Error | null) => void): void;
_writev(
chunks: Array<{ chunk: any; encoding: string }>,
callback: (error?: Error | null) => void,
): void;
_final(callback: (error?: Error | null) => void): void;
write(chunk: Buffer | string, callback?: (error?: Error | null) => void): boolean;
write(
chunk: Buffer | string,
encoding: string,
callback?: (error?: Error | null) => void,
): boolean;
/* An object-mode stream's values (the encoding argument reaches
* _write as passed). */
write(chunk: any, callback?: (error?: Error | null) => void): boolean;
write(
chunk: any,
encoding: ObjectModeEncoding,
callback?: (error?: Error | null) => void,
): boolean;
end(callback?: () => void): this;
end(chunk: Buffer | string, callback?: () => void): this;
end(chunk: Buffer | string, encoding: string, callback?: () => void): this;
end(chunk: any, callback?: () => void): this;
end(chunk: any, encoding: ObjectModeEncoding, callback?: () => void): this;
cork(): void;
uncork(): void;
setDefaultEncoding(encoding: string): this;
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableLength: number;
readonly writableHighWaterMark: number;
readonly writableObjectMode: boolean;
readonly writableNeedDrain: boolean;
readonly writableCorked: number;
readonly allowHalfOpen: boolean;
on(event: "data", listener: (chunk: any) => void): this;
on(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
once(event: "data", listener: (chunk: any) => void): this;
once(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
addListener(event: "data", listener: (chunk: any) => void): this;
addListener(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
addListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "data", listener: (chunk: any) => void): this;
prependListener(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "data", listener: (chunk: any) => void): this;
prependOnceListener(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
off(event: "data", listener: (chunk: any) => void): this;
off(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
off(event: "error", listener: (err: Error) => void): this;
off(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
off(event: string, listener: (...args: any[]) => void): this;
removeListener(event: "data", listener: (chunk: any) => void): this;
removeListener(
event: "end" | "close" | "readable" | "pause" | "resume" | "drain" | "finish",
listener: () => void,
): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "pipe" | "unpipe", listener: (src: Readable) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
}
class Transform extends Duplex {
constructor(opts: ObjectTransformOptions);
constructor(opts: StringTransformOptions);
constructor(opts?: TransformOptions);
/* The underscore-method surface (see Readable). */
_transform(
chunk: any,
encoding: string,
callback: (error?: Error | null, data?: any) => void,
): void;
_flush(callback: (error?: Error | null, data?: any) => void): void;
}
class PassThrough extends Transform {
constructor(opts: ObjectTransformOptions);
constructor(opts: StringTransformOptions);
constructor(opts?: TransformOptions);
}
/* addAbortSignal(signal, stream): the stream, destroyed with an
* AbortError (cause: signal.reason) when the signal aborts. */
function addAbortSignal<T extends Readable | Writable>(signal: AbortSignal, stream: T): T;
/* pipeline(...stages, callback): the last stream, or the object-mode
* PassThrough that a function destination feeds. */
type PipelineResult<T extends unknown[]> = T extends [
...unknown[],
infer D,
(...args: any[]) => unknown,
]
? D extends (...args: any[]) => unknown
? PassThrough
: D
: unknown;
function pipeline<T extends unknown[]>(...streams: T): PipelineResult<T>;
/* util.promisify's pipeline overload matches only pipeline itself: a
* generic signature alone admits every function. */
namespace pipeline {
const __promisify__: typeof promises.pipeline;
}
/* A compose stage: a stream, an async generator function over the
* previous stage, or (first) an iterable, async iterable or web
* ReadableStream. */
type ComposeStage =
| Readable
| Writable
| Iterable<unknown>
| AsyncIterable<unknown>
| globalThis.ReadableStream
| ((source: any, options?: { signal: AbortSignal }) => unknown);
/* compose(...streams): a Duplex that writes to the first stage and
* reads from the last, with the stages running as a pipeline. */
function compose(...streams: ComposeStage[]): Duplex;
/* finished's options: readable/writable choose which ends count,
* error: false ignores 'error' events, signal aborts the wait. */
interface FinishedOptions {
readable?: boolean;
writable?: boolean;
error?: boolean;
signal?: AbortSignal;
}
function finished(stream: unknown, callback: (err?: Error | null) => void): () => void;
function finished(
stream: unknown,
options: FinishedOptions | null,
callback: (err?: Error | null) => void,
): () => void;
/* Folds to the TARGET platform's default at compile time (win32 16384,
* else 65536 — Node's own state.js split); literal argument only. */
function getDefaultHighWaterMark(objectMode: boolean): number;
/* The promise pipeline's result: a last stage that is an async
* function resolves the promise with its value (before the options
* argument, when one follows). */
type PipelinePromise<T extends unknown[]> = T extends [
...unknown[],
(...args: any[]) => Promise<infer P>,
]
? Promise<P>
: T extends [
...unknown[],
(...args: any[]) => Promise<infer P>,
{ signal?: AbortSignal; end?: boolean },
]
? Promise<P>
: Promise<void>;
namespace promises {
function pipeline<T extends unknown[]>(...streams: T): PipelinePromise<T>;
function finished(
stream: unknown,
options?: FinishedOptions & { cleanup?: boolean },
): Promise<void>;
}
class Stream extends EventEmitter {}
export {
Readable,
Writable,
Duplex,
Transform,
PassThrough,
Stream,
addAbortSignal,
pipeline,
compose,
finished,
getDefaultHighWaterMark,
promises,
};
export type {
ReadableOptions,
WritableOptions,
DuplexOptions,
TransformOptions,
FinishedOptions,
PipelinePromise,
};
}
declare module "node:stream" {
import stream = require("stream");
export = stream;
}
@@ -0,0 +1,20 @@
/* node:string_decoder — StringDecoder over Node's whole encoding set:
* write() decodes complete sequences and buffers a trailing partial one
* across chunk boundaries (utf8's truncated sequence, base64's mod-3
* remainder, utf16le's odd byte / trailing lead surrogate; latin1, ascii
* and hex are stateless); end() flushes the buffered partial. `encoding`
* answers the normalized name. Node's exact algorithms (SEMANTICS.md);
* the encoding must be a literal, and end(buffer) fences — write the
* buffer, then end(). */
declare module "string_decoder" {
export class StringDecoder {
constructor(encoding?: BufferEncoding);
readonly encoding: string;
write(buffer: Uint8Array): string;
end(buffer?: Uint8Array): string;
}
}
declare module "node:string_decoder" {
export * from "string_decoder";
}
+236
View File
@@ -0,0 +1,236 @@
/// <reference path="./assert.d.ts" />
/* node:assert — the static assertion surface. The module object IS a
* callable function (`assert(x)` is `assert.ok(x)`), so the declaration
* is the callable-namespace `export =` shape and BOTH `import assert
* from "node:assert"` and `const assert = require("assert")` bind the
* callable; named imports take the members. Failures throw
* AssertionError (name "AssertionError", code "ERR_ASSERTION" — catch and
* read .name/.message/.code). strictEqual/deepStrictEqual compare with
* Object.is over scalars; deepStrictEqual compares composites
* structurally per their static types. The messages here are plain
* strings (Node accepts Errors — that form fences per site), and the
* shallow legacy pair (equal/notEqual) follows Node's == coercions for
* primitive and primitive-union operands, including Node v24's NaN
* exception. deepEqual/notDeepEqual remain declared-but-fenced;
* assert/strict's loose names alias the strict forms and lower. */
/* node:test — the in-process test runner (prefix-only in Node too:
* require("test") is MODULE_NOT_FOUND). test/it register tests (sync and
* async bodies, skip/todo/only options and method twins), describe/suite
* group them (bodies run at registration, Node's collection phase),
* before/after/beforeEach/afterEach hook the enclosing suite, and the
* TestContext argument carries subtests (t.test), t.skip/t.todo,
* t.diagnostic, and t.assert. mock/run/snapshot are DECLARED so real
* suites typecheck but fence at their use sites (no lowering). */
declare module "node:test" {
type TestFn = (t: TestContext) => void | Promise<void>;
type SuiteFn = (s: SuiteContext) => void;
type HookFn = (c: TestContext | SuiteContext) => void | Promise<void>;
/* The describe/suite callback's context, and the before/after hook
* context of a suite. */
interface SuiteContext {
readonly name: string;
readonly fullName: string;
readonly filePath: string | undefined;
readonly attempt: number;
readonly passed: boolean;
diagnostic(message: string): void;
}
interface TestOptions {
skip?: boolean | string;
todo?: boolean | string;
only?: boolean;
concurrency?: number | boolean;
timeout?: number;
plan?: number;
}
interface TestContext {
readonly name: string;
readonly fullName: string;
readonly filePath: string | undefined;
readonly attempt: number;
readonly passed: boolean;
readonly workerId: number | undefined;
readonly tags: readonly string[];
readonly assert: TestContextAssert;
readonly mock: MockTracker;
test(name?: string, fn?: TestFn): Promise<void>;
test(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>;
test(options?: TestOptions, fn?: TestFn): Promise<void>;
test(fn?: TestFn): Promise<void>;
skip(message?: string): void;
todo(message?: string): void;
diagnostic(message: string): void;
plan(count: number): void;
after(fn: HookFn): void;
before(fn: HookFn): void;
beforeEach(fn: HookFn): void;
afterEach(fn: HookFn): void;
}
interface AssertSnapshotOptions {
readonly serializers?: ReadonlyArray<(value: any) => any> | undefined;
}
interface TestContextAssert {
snapshot(value: any, options?: AssertSnapshotOptions): void;
fileSnapshot(value: any, path: string, options?: AssertSnapshotOptions): void;
ok(value: unknown, message?: string): void;
strictEqual(actual: unknown, expected: unknown, message?: string): void;
notStrictEqual(actual: unknown, expected: unknown, message?: string): void;
deepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
notDeepStrictEqual(actual: unknown, expected: unknown, message?: string): void;
equal(actual: unknown, expected: unknown, message?: string): void;
notEqual(actual: unknown, expected: unknown, message?: string): void;
deepEqual(actual: unknown, expected: unknown, message?: string): void;
notDeepEqual(actual: unknown, expected: unknown, message?: string): void;
fail(message?: string): never;
throws(fn: () => unknown, expected?: unknown, message?: string): void;
match(value: string, regExp: RegExp, message?: string): void;
doesNotMatch(value: string, regExp: RegExp, message?: string): void;
}
/* The name, options and function are each optional, as in Node: a test
* without a name takes the function's name, or "<anonymous>". */
function test(name?: string, fn?: TestFn): Promise<void>;
function test(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>;
function test(options?: TestOptions, fn?: TestFn): Promise<void>;
function test(fn?: TestFn): Promise<void>;
namespace test {
function skip(name?: string, fn?: TestFn): Promise<void>;
function skip(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>;
function skip(options?: TestOptions, fn?: TestFn): Promise<void>;
function skip(fn?: TestFn): Promise<void>;
function todo(name?: string, fn?: TestFn): Promise<void>;
function todo(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>;
function todo(options?: TestOptions, fn?: TestFn): Promise<void>;
function todo(fn?: TestFn): Promise<void>;
function only(name?: string, fn?: TestFn): Promise<void>;
function only(name?: string, options?: TestOptions, fn?: TestFn): Promise<void>;
function only(options?: TestOptions, fn?: TestFn): Promise<void>;
function only(fn?: TestFn): Promise<void>;
}
const it: typeof test;
function describe(name?: string, fn?: SuiteFn): void;
function describe(name?: string, options?: TestOptions, fn?: SuiteFn): void;
function describe(options?: TestOptions, fn?: SuiteFn): void;
function describe(fn?: SuiteFn): void;
namespace describe {
function skip(name?: string, fn?: SuiteFn): void;
function skip(name?: string, options?: TestOptions, fn?: SuiteFn): void;
function skip(options?: TestOptions, fn?: SuiteFn): void;
function skip(fn?: SuiteFn): void;
function todo(name?: string, fn?: SuiteFn): void;
function todo(name?: string, options?: TestOptions, fn?: SuiteFn): void;
function todo(options?: TestOptions, fn?: SuiteFn): void;
function todo(fn?: SuiteFn): void;
function only(name?: string, fn?: SuiteFn): void;
function only(name?: string, options?: TestOptions, fn?: SuiteFn): void;
function only(options?: TestOptions, fn?: SuiteFn): void;
function only(fn?: SuiteFn): void;
}
const suite: typeof describe;
function before(fn: HookFn): void;
function after(fn: HookFn): void;
function beforeEach(fn: HookFn): void;
function afterEach(fn: HookFn): void;
/* The mock function surface: mock.fn, mock.method and their t.mock
* twins, the tracker's restoreAll and reset, and the calls log and the
* implementation controls on fn.mock. */
interface MockFunctionCall<
F extends Function,
ReturnType = F extends (...args: any) => infer T ? T : unknown,
Args = F extends (...args: infer Y) => any ? Y : unknown[],
> {
arguments: Args;
error: unknown | undefined;
result: ReturnType | undefined;
this: unknown;
}
interface MockFunctionContext<F extends Function> {
readonly calls: MockFunctionCall<F>[];
callCount(): number;
mockImplementation(implementation: F): void;
mockImplementationOnce(implementation: F, onCall?: number): void;
resetCalls(): void;
restore(): void;
}
type Mock<F extends Function> = F & { mock: MockFunctionContext<F> };
interface MockFunctionOptions {
times?: number;
}
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
interface MockTracker {
fn<F extends Function = (...args: any[]) => undefined>(original?: F): Mock<F>;
fn<F extends Function = (...args: any[]) => undefined, Implementation extends Function = F>(
original?: F,
implementation?: Implementation,
): Mock<F | Implementation>;
method<MockedObject extends object, MethodName extends FunctionPropertyNames<MockedObject>>(
object: MockedObject,
methodName: MethodName,
options?: MockFunctionOptions,
): MockedObject[MethodName] extends Function ? Mock<MockedObject[MethodName]> : never;
method<
MockedObject extends object,
MethodName extends FunctionPropertyNames<MockedObject>,
Implementation extends Function,
>(
object: MockedObject,
methodName: MethodName,
implementation: Implementation,
options?: MockFunctionOptions,
): MockedObject[MethodName] extends Function
? Mock<MockedObject[MethodName] | Implementation>
: never;
reset(): void;
restoreAll(): void;
readonly timers: MockTimers;
}
interface MockTimersOptions {
apis: ReadonlyArray<"setInterval" | "setTimeout" | "setImmediate" | "Date">;
now?: number | Date | undefined;
}
interface MockTimers {
enable(options?: MockTimersOptions): void;
setTime(milliseconds?: number): void;
reset(): void;
tick(milliseconds?: number): void;
runAll(): void;
[Symbol.dispose](): void;
}
const mock: MockTracker;
/* The context of the test, suite or hook running in the current async
* context; undefined outside one. */
function getTestContext(): TestContext | SuiteContext | undefined;
/* Declared for typechecking only — every use fences (no lowering).
* `assert` is the module-level custom-assertion registry (v24's
* `const { assert } = require('node:test')`), not TestContext.assert. */
const assert: { register(name: string, fn: (...args: unknown[]) => unknown): void };
function run(options?: unknown): unknown;
function snapshot(...args: unknown[]): unknown;
export {
test,
it,
describe,
suite,
before,
after,
beforeEach,
afterEach,
mock,
assert,
getTestContext,
run,
snapshot,
TestContext,
SuiteContext,
TestOptions,
Mock,
MockFunctionContext,
MockFunctionCall,
MockTracker,
MockTimers,
MockTimersOptions,
};
export default test;
}
@@ -0,0 +1,31 @@
/* node:timers/promises — the promisified pair the Node test harness leans
* on (`await setTimeout(ms)` as a sleep). setTimeout and setImmediate
* settle with their resolve value (undefined without one) from the shared
* timer heap and the immediate queue; setInterval(delay, value) lowers to a
* typed async iterator. The options object takes `ref`; AbortSignal
* options remain declared surface that fences per site. */
declare module "node:timers/promises" {
export interface TimerOptions {
ref?: boolean;
signal?: AbortSignal;
}
export function setTimeout<T = void>(
delay?: number,
value?: T,
options?: TimerOptions,
): Promise<T>;
export function setImmediate<T = void>(value?: T, options?: TimerOptions): Promise<T>;
export function setInterval<T = unknown>(
delay?: number,
value?: T,
options?: unknown,
): AsyncGenerator<T, void, undefined>;
export const scheduler: {
wait(delay?: number, options?: TimerOptions): Promise<void>;
yield(): Promise<void>;
};
}
declare module "timers/promises" {
export * from "node:timers/promises";
}
+28
View File
@@ -0,0 +1,28 @@
/* node:timers — the module twins of the timer globals (Node's timers
* module re-exports them: require('timers').setTimeout IS setTimeout).
* Named imports, destructured requires, and namespace calls all lower to
* the same libCalls as the globals; the surface beyond these six
* (enroll/unenroll, promises) fences per member. */
declare module "node:timers" {
export function setTimeout(callback: () => void, ms?: number): Timeout;
export function setTimeout(
callback: (...args: never[]) => void,
ms?: number,
...args: unknown[]
): Timeout;
export function clearTimeout(handle?: Timeout | number | null | undefined): void;
export function setInterval(callback: () => void, ms?: number): Timeout;
export function setInterval(
callback: (...args: never[]) => void,
ms?: number,
...args: unknown[]
): Timeout;
export function clearInterval(handle?: Timeout | number | null | undefined): void;
export function setImmediate(callback: () => void): Immediate;
export function setImmediate(callback: (...args: never[]) => void, ...args: unknown[]): Immediate;
export function clearImmediate(handle?: Immediate | null | undefined): void;
}
declare module "timers" {
export * from "node:timers";
}
+169
View File
@@ -0,0 +1,169 @@
/// <reference path="./crypto.d.ts" />
/// <reference path="./net.d.ts" />
/* node:tls — the TLS server slice (scr_tls.c over scr_net.c with the
* vendored mbedTLS; linked only into using binaries).
* createServer({ cert, key }, handler) returns a net.Server; the handler
* is Node's 'secureConnection' — it fires post-handshake with a socket
* that behaves exactly like a net socket (write/end/destroy/pipe and the
* data/end/close/error events are the same lowered surface). cert/key
* are PEM strings or Buffers. Handshake failures tear the socket down
* without emitting an event, Node's default for 'tlsClientError' with no listener. */
declare module "tls" {
import { Server as NetServer, Socket } from "net";
/** tls.Server: a net server whose connections handshake first. */
export interface Server extends NetServer {
/* serve `context` to clients whose SNI name matches `hostname` ('*'
* matches within one label); the newest match wins */
addContext(hostname: string, context: TlsOptions | SecureContext): void;
/* new connections serve a context made from `options` */
setSecureContext(options: TlsOptions): void;
}
export interface TlsOptions {
/* Optional in the DECLARATION only (real Node programs build these
* literals with every TLS knob): the lowering still requires both —
* a literal without them fences at the call site. */
cert?: string | Uint8Array;
key?: string | Uint8Array;
/* The options-record stance (see http.RequestOptions): every key
* typechecks; the option walk fences documented-but-unlowered keys
* by name and drops undocumented ones like Node. */
[option: string]: unknown;
}
export function createServer(
options: TlsOptions,
secureConnectionListener?: (socket: TLSSocket) => void,
): Server;
/** TLSSocket — post-handshake it IS a net socket to every lowered
* member (the mapping collapses it onto the socket kind; the
* secureConnect/session events ride the shared socket declarations).
* The TLS extras: authorized/authorizationError answer Node's verify
* split — authorizationError is the verify-failure CODE STRING
* (DEPTH_ZERO_SELF_SIGNED_CERT, ...), or null. */
export interface TLSSocket extends Socket {
readonly encrypted: true;
authorized: boolean;
authorizationError: string | null;
/* null before the handshake, then the negotiated protocol or false */
readonly alpnProtocol: string | false | null;
/* "TLSv1.2" or "TLSv1.3"; null before the handshake and after close */
getProtocol(): string | null;
/* OpenSSL's suite name, the IANA name and the suite's version */
getCipher(): CipherNameAndProtocol;
/* whether the handshake resumed a cached session */
isSessionReused(): boolean;
/* the peer's certificate: {} before the handshake or without one,
* null once the socket is destroyed; detailed adds issuerCertificate */
getPeerCertificate(detailed: true): DetailedPeerCertificate;
getPeerCertificate(detailed?: false): PeerCertificate;
getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate;
/* the certificate this socket serves, the same way */
getCertificate(): PeerCertificate | object | null;
/* a new X509Certificate on each call, or undefined without one */
getPeerX509Certificate(): import("crypto").X509Certificate | undefined;
getX509Certificate(): import("crypto").X509Certificate | undefined;
}
/* A certificate as getPeerCertificate() and X509Certificate's
* toLegacyObject() answer it: subject and issuer map attribute short
* names to values, infoAccess its "<method> - <type>" keys to values. */
export interface PeerCertificate {
subject: { [attribute: string]: string | string[] };
issuer: { [attribute: string]: string | string[] };
subjectaltname?: string;
infoAccess?: { [key: string]: string[] };
ca: boolean;
modulus?: string;
exponent?: string;
pubkey?: Buffer;
bits?: number;
valid_from: string;
valid_to: string;
fingerprint: string;
fingerprint256: string;
fingerprint512: string;
ext_key_usage?: string[];
serialNumber: string;
raw: Buffer;
asn1Curve?: string;
nistCurve?: string;
}
/* getPeerCertificate(true): each certificate links to its issuer; a
* self-issued root is its own issuerCertificate */
export interface DetailedPeerCertificate extends PeerCertificate {
issuerCertificate: DetailedPeerCertificate;
}
/** new tls.TLSSocket(socket, options): the server-mode wrap of an open
* socket (a server connection or an http CONNECT socket). The options
* record reads at runtime; isServer, cert, key, secureContext,
* ALPNProtocols, minVersion and maxVersion are implemented. */
export interface TLSSocketOptions {
isServer?: boolean;
cert?: string | Uint8Array;
key?: string | Uint8Array;
secureContext?: SecureContext;
ALPNProtocols?: string[] | Uint8Array;
minVersion?: string;
maxVersion?: string;
[option: string]: unknown;
}
export const TLSSocket: new (socket: Socket, options: TLSSocketOptions) => TLSSocket;
export interface CipherNameAndProtocol {
name: string;
standardName: string;
version: string;
}
export const DEFAULT_MIN_VERSION: string;
export const DEFAULT_MAX_VERSION: string;
/** tls.connect options — the RUNTIME options record (members read at
* runtime; port/host/socket/rejectUnauthorized/ca/servername are the
* honestly-implemented set, every other documented member throws the
* runtime fence — the options-record stance's divergence-66 shape). */
export interface ConnectionOptions {
port?: number;
host?: string;
/* an open socket to run the client handshake over */
socket?: Socket;
rejectUnauthorized?: boolean;
ca?: string | Uint8Array | ReadonlyArray<string | Uint8Array>;
servername?: string;
[option: string]: unknown;
}
export function connect(
options: ConnectionOptions,
secureConnectListener?: () => void,
): TLSSocket;
export function connect(
port: number,
options?: ConnectionOptions,
secureConnectListener?: () => void,
): TLSSocket;
export function connect(
port: number,
host?: string,
options?: ConnectionOptions,
secureConnectListener?: () => void,
): TLSSocket;
/** An opaque parsed cert/key pair — what an SNI callback answers with
* (the value is a runtime handle; the members are runtime-internal). */
export interface SecureContext {}
/* @types/node's name for createSecureContext's options */
export type SecureContextOptions = TlsOptions;
export function createSecureContext(options: TlsOptions): SecureContext;
/** The CA-store introspection surface (scr_tls_ca.c): per-type cached
* PEM string arrays. The host bundle stands in for Node's compiled-in
* Mozilla roots ('bundled', and rootCertificates) AND the platform
* store ('system') — the Windows certificate stores or POSIX bundle probe;
* 'extra' reads NODE_EXTRA_CA_CERTS. An unknown type string throws
* Node's ERR_INVALID_ARG_VALUE TypeError. */
export function getCACertificates(type?: string): string[];
export const rootCertificates: readonly string[];
/** Replaces the 'default' set (deduped) and the trust anchors the TLS
* client verifies against; a certificate-free non-empty array throws
* Node's ERR_CRYPTO_OPERATION_FAILED Error. */
export function setDefaultCACertificates(certs: readonly string[]): void;
}
declare module "node:tls" {
export * from "tls";
}
+95
View File
@@ -0,0 +1,95 @@
/// <reference path="./querystring.d.ts" />
/* node:url — the file-URL bridge pair. fileURLToPath accepts a URL value
* or a URL string and throws Node's TypeErrors (non-file scheme, encoded
* slashes, non-empty host); pathToFileURL resolves the path and percent-
* encodes it into a file: URL. The legacy API: parse() answers a Url
* object, format() serializes a Url-shaped object, a string, or a URL,
* resolve() resolves one URL string against another, the domain pair
* converts a hostname to and from its Punycode form, and urlToHttpOptions
* builds http.request options from a URL. */
declare module "url" {
export type URL = globalThis.URL;
export type URLSearchParams = globalThis.URLSearchParams;
export const URL: typeof globalThis.URL;
export const URLSearchParams: typeof globalThis.URLSearchParams;
export function fileURLToPath(url: string | URL, options?: { windows?: boolean }): string;
export function fileURLToPathBuffer(url: string | URL, options?: { windows?: boolean }): Buffer;
export function pathToFileURL(path: string, options?: { windows?: boolean }): URL;
export interface UrlObject {
auth?: string | null | undefined;
hash?: string | null | undefined;
host?: string | null | undefined;
hostname?: string | null | undefined;
href?: string | null | undefined;
pathname?: string | null | undefined;
protocol?: string | null | undefined;
search?: string | null | undefined;
slashes?: boolean | null | undefined;
port?: string | number | null | undefined;
query?: string | null | import("querystring").ParsedUrlQueryInput | undefined;
}
export interface Url {
auth: string | null;
hash: string | null;
host: string | null;
hostname: string | null;
href: string;
path: string | null;
pathname: string | null;
protocol: string | null;
search: string | null;
slashes: boolean | null;
port: string | null;
query: string | null | import("querystring").ParsedUrlQuery;
}
export interface UrlWithParsedQuery extends Url {
query: import("querystring").ParsedUrlQuery;
}
export interface UrlWithStringQuery extends Url {
query: string | null;
}
export interface URLFormatOptions {
auth?: boolean | undefined;
fragment?: boolean | undefined;
search?: boolean | undefined;
unicode?: boolean | undefined;
}
export function parse(
urlString: string,
parseQueryString?: false,
slashesDenoteHost?: boolean,
): UrlWithStringQuery;
export function parse(
urlString: string,
parseQueryString: true,
slashesDenoteHost?: boolean,
): UrlWithParsedQuery;
export function parse(
urlString: string,
parseQueryString: boolean,
slashesDenoteHost?: boolean,
): Url;
export function format(urlObject: URL, options?: URLFormatOptions): string;
export function format(urlObject: UrlObject | string): string;
export function resolve(from: string, to: string): string;
export function domainToASCII(domain: string): string;
export function domainToUnicode(domain: string): string;
/** urlToHttpOptions's null-prototype request options. */
export interface UrlHttpOptions {
protocol: string;
hostname: string;
hash: string;
search: string;
pathname: string;
path: string;
href: string;
port?: number;
auth?: string;
}
export function urlToHttpOptions(url: URL): UrlHttpOptions;
}
declare module "node:url" {
export * from "url";
}
+50
View File
@@ -0,0 +1,50 @@
/* node:util/types — native runtime brands. Other forms retain their
* per-member lowering boundaries. */
declare module "util/types" {
export function isAnyArrayBuffer(value: unknown): boolean;
export function isArrayBuffer(value: unknown): value is ArrayBuffer;
export function isArrayBufferView(value: unknown): value is ArrayBufferView;
export function isDataView(value: unknown): value is DataView;
export function isTypedArray(value: unknown): boolean;
export function isUint8Array(value: unknown): value is Uint8Array;
export function isUint8ClampedArray(value: unknown): value is Uint8ClampedArray;
export function isUint16Array(value: unknown): value is Uint16Array;
export function isUint32Array(value: unknown): value is Uint32Array;
export function isInt8Array(value: unknown): value is Int8Array;
export function isInt16Array(value: unknown): value is Int16Array;
export function isInt32Array(value: unknown): value is Int32Array;
export function isFloat16Array(value: unknown): value is Float16Array;
export function isFloat32Array(value: unknown): value is Float32Array;
export function isFloat64Array(value: unknown): value is Float64Array;
export function isMap(value: unknown): value is Map<unknown, unknown>;
export function isSet(value: unknown): value is Set<unknown>;
export function isWeakMap(value: unknown): value is WeakMap<object, unknown>;
export function isWeakSet(value: unknown): value is WeakSet<object>;
export function isRegExp(value: unknown): value is RegExp;
export function isNativeError(value: unknown): value is Error;
export function isPromise(value: unknown): value is Promise<unknown>;
export function isProxy(value: unknown): boolean;
export function isAsyncFunction(value: unknown): boolean;
export function isGeneratorFunction(value: unknown): boolean;
export function isGeneratorObject(value: unknown): boolean;
export function isModuleNamespaceObject(value: unknown): boolean;
export function isDate(value: unknown): value is Date;
export function isSharedArrayBuffer(value: unknown): value is SharedArrayBuffer;
export function isMapIterator(value: unknown): boolean;
export function isSetIterator(value: unknown): boolean;
export function isKeyObject(value: unknown): boolean;
export function isNumberObject(value: unknown): boolean;
export function isStringObject(value: unknown): boolean;
export function isBooleanObject(value: unknown): boolean;
export function isBigIntObject(value: unknown): boolean;
export function isSymbolObject(value: unknown): boolean;
export function isBoxedPrimitive(value: unknown): boolean;
export function isBigInt64Array(value: unknown): value is BigInt64Array;
export function isBigUint64Array(value: unknown): value is BigUint64Array;
export function isCryptoKey(value: unknown): boolean;
export function isExternal(value: unknown): boolean;
}
declare module "node:util/types" {
export * from "util/types";
}
+396
View File
@@ -0,0 +1,396 @@
/// <reference path="./child_process.d.ts" />
/// <reference path="./crypto.d.ts" />
/// <reference path="./dns.d.ts" />
/// <reference path="./fs.d.ts" />
/// <reference path="./stream.d.ts" />
/// <reference path="./stream-promises.d.ts" />
/// <reference path="./timers-promises.d.ts" />
/// <reference path="./util-types.d.ts" />
/// <reference path="./zlib.d.ts" />
/* node:util — compile-time projections for child_process.execFile,
* child_process.exec and fs.readFile. The first two retain Node's custom
* { stdout, stderr } result; the last resolves the callback's data
* argument. Other targets and bare
* promisify values fence per site. */
declare module "util" {
export * as types from "util/types";
export function getSystemErrorName(err: number): string;
export function getSystemErrorMessage(err: number): string;
export function getSystemErrorMap(): Map<number, [string, string]>;
export function stripVTControlCharacters(str: string): string;
export function toUSVString(string: string): string;
export function isDeepStrictEqual(val1: unknown, val2: unknown, skipPrototype?: boolean): boolean;
export function styleText(
format: string | readonly string[],
text: string,
options?: { validateStream?: boolean; stream?: unknown },
): string;
export function parseEnv(content: string): { [key: string]: string | undefined };
export function inherits(constructor: unknown, superConstructor: unknown): void;
export class MIMEType {
constructor(input: string | { toString: () => string });
static parse(input: string | { toString: () => string }): MIMEType | null;
type: string;
subtype: string;
readonly essence: string;
readonly params: MIMEParams;
toString(): string;
toJSON(): string;
}
export class MIMEParams {
delete(name: string): void;
entries(): IterableIterator<[name: string, value: string]>;
get(name: string): string | null;
has(name: string): boolean;
keys(): IterableIterator<string>;
set(name: string, value: string): void;
values(): IterableIterator<string>;
toString(): string;
toJSON(): string;
[Symbol.iterator](): IterableIterator<[name: string, value: string]>;
}
export type DiffEntry = [operation: -1 | 0 | 1, value: string];
export function diff(
actual: string | readonly string[],
expected: string | readonly string[],
): DiffEntry[];
export interface DebounceOptions {
leading?: boolean;
rejectOnCancel?: boolean;
signal?: AbortSignal;
}
/** Every call answers a promise of the result of the call it waits for. */
export interface DebouncedFunction<T extends (...args: any[]) => any> {
(...args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
cancel(reason?: unknown): void;
flush(): void;
ref(): this;
unref(): this;
readonly pending: Promise<Awaited<ReturnType<T>>> | null;
readonly pendingCount: number;
}
export function debounce<T extends (...args: any[]) => any>(
fn: T,
wait: number,
options?: DebounceOptions,
): DebouncedFunction<T>;
export interface ThrottleOptions {
concurrency?: number;
maxPending?: number;
overflow?: "queue" | "drop";
signal?: AbortSignal;
strict?: boolean;
}
export interface ThrottledFunction<T extends (...args: any[]) => any> {
(...args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
cancel(reason?: unknown): void;
hasImmediateCapacity(): boolean;
ref(): this;
unref(): this;
readonly pending: Promise<Awaited<ReturnType<T>>> | null;
readonly pendingCount: number;
readonly activeCount: number;
}
export function throttle<T extends (...args: any[]) => any>(
fn: T,
limit: number,
interval: number,
options?: ThrottleOptions,
): ThrottledFunction<T>;
/** Resolves with the abort event once `signal` aborts, or with undefined
* when it already has. */
export function aborted(signal: AbortSignal, resource: any): Promise<unknown>;
/** 128 plus the number of the signal, the exit code of a process it terminates. */
export function convertProcessSignalToExitCode(signalCode: string): number;
/** @deprecated Since v4.0.0 - Use `Array.isArray()` instead. */
export function isArray(object: unknown): object is unknown[];
/** @deprecated Since v6.0.0 - Use `Object.assign()` instead. Answers target itself. */
export function _extend<T extends object>(target: T, source: object | null | undefined): T;
export interface DeprecateOptions {
modifyPrototype?: boolean;
}
export function deprecate<T extends Function>(
fn: T,
msg: string,
code?: string,
options?: DeprecateOptions,
): T;
/* The callback receives null on success and the rejection reason
* otherwise (falsy reasons arrive as ERR_FALSY_VALUE_REJECTION). */
export function callbackify(
fn: () => Promise<void>,
): (callback: (err: NodeJS.ErrnoException | null) => void) => void;
export function callbackify<TResult>(
fn: () => Promise<TResult>,
): (callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void;
export function callbackify<T1>(
fn: (arg1: T1) => Promise<void>,
): (arg1: T1, callback: (err: NodeJS.ErrnoException | null) => void) => void;
export function callbackify<T1, TResult>(
fn: (arg1: T1) => Promise<TResult>,
): (arg1: T1, callback: (err: NodeJS.ErrnoException | null, result: TResult) => void) => void;
export function callbackify<T1, T2>(
fn: (arg1: T1, arg2: T2) => Promise<void>,
): (arg1: T1, arg2: T2, callback: (err: NodeJS.ErrnoException | null) => void) => void;
export function callbackify<T1, T2, TResult>(
fn: (arg1: T1, arg2: T2) => Promise<TResult>,
): (
arg1: T1,
arg2: T2,
callback: (err: NodeJS.ErrnoException | null, result: TResult) => void,
) => void;
export function callbackify<T1, T2, T3>(
fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<void>,
): (arg1: T1, arg2: T2, arg3: T3, callback: (err: NodeJS.ErrnoException | null) => void) => void;
export function callbackify<T1, T2, T3, TResult>(
fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<TResult>,
): (
arg1: T1,
arg2: T2,
arg3: T3,
callback: (err: NodeJS.ErrnoException | null, result: TResult) => void,
) => void;
export type DebugLoggerFunction = (msg: string, ...param: unknown[]) => void;
export interface DebugLogger extends DebugLoggerFunction {
enabled: boolean;
}
export function debuglog(
section: string,
callback?: (fn: DebugLoggerFunction) => void,
): DebugLogger;
export { debuglog as debug };
export type TextEncoder = globalThis.TextEncoder;
export type TextDecoder = globalThis.TextDecoder;
export var TextEncoder: typeof globalThis.TextEncoder;
export var TextDecoder: typeof globalThis.TextDecoder;
/* An untyped function: an `any` value, or a function whose parameters
* are untyped (JavaScript's `(value, callback) => ...`), the only
* parameters that accept this object type. The promisified function is
* untyped too. It comes first because such functions match every other
* overload. */
export function promisify(fn: (...args: { readonly "scriptc:untyped": true }[]) => unknown): any;
/* stream.pipeline's overload comes next: its __promisify__ member keeps
* every other target out of it. */
export function promisify(
fn: typeof import("node:stream").pipeline,
): typeof import("node:stream/promises").pipeline;
export function promisify(
fn: typeof import("node:fs").readFile,
): (path: string, encoding: "utf8" | "utf-8") => Promise<string>;
export function promisify(
fn: (file: string, args?: string[] | null, options?: object) => unknown,
): (
file: string,
args?: string[],
options?: {
encoding?: "utf8" | "utf-8";
cwd?: string;
env?: { [k: string]: string | undefined };
timeout?: number;
maxBuffer?: number;
killSignal?: string;
windowsHide?: boolean;
},
) => Promise<{ stdout: string; stderr: string }>;
export function promisify(
fn: typeof globalThis.setTimeout,
): typeof import("node:timers/promises").setTimeout;
export function promisify(
fn: typeof globalThis.setImmediate,
): typeof import("node:timers/promises").setImmediate;
export function promisify(fn: typeof import("node:child_process").exec): (
command: string,
options?: {
encoding?: "utf8" | "utf-8";
cwd?: string;
env?: { [k: string]: string | undefined };
timeout?: number;
maxBuffer?: number;
killSignal?: string;
windowsHide?: boolean;
},
) => Promise<{ stdout: string; stderr: string }>;
/* The zlib callback one-shots (deflate, inflate, deflateRaw, inflateRaw,
* gzip, gunzip, unzip) share one type. */
export function promisify(
fn: typeof import("node:zlib").gzip,
): (data: string | Uint8Array, options?: import("node:zlib").ZlibOptions) => Promise<Buffer>;
export function promisify(
fn: typeof import("node:stream").finished,
): typeof import("node:stream/promises").finished;
/* The crypto callback functions: the promise settles with the callback's
* value. */
export function promisify(
fn: typeof import("node:crypto").randomBytes,
): (size: number) => Promise<Buffer>;
export function promisify(
fn: typeof import("node:crypto").pbkdf2,
): (
password: string | Uint8Array,
salt: string | Uint8Array,
iterations: number,
keylen: number,
digest: string,
) => Promise<Buffer>;
export function promisify(
fn: typeof import("node:crypto").scrypt,
): (
password: import("node:crypto").BinaryLike,
salt: import("node:crypto").BinaryLike,
keylen: number,
options?: import("node:crypto").ScryptOptions,
) => Promise<Buffer>;
export function promisify(
fn: typeof import("node:crypto").hkdf,
): (
digest: string,
ikm: import("node:crypto").BinaryLike | import("node:crypto").KeyObject,
salt: import("node:crypto").BinaryLike,
info: import("node:crypto").BinaryLike,
keylen: number,
) => Promise<ArrayBuffer>;
/* A callback-only function (`obj.close.bind(obj)`): before the targets
* whose leading parameters would otherwise capture it. Builtins that take
* arguments before their callback never match these. */
export function promisify<TResult>(
fn: (callback: (err: any, result: TResult) => void) => void,
): () => Promise<TResult>;
export function promisify(fn: (callback: (err?: any) => void) => void): () => Promise<void>;
export function promisify(
fn: typeof import("node:crypto").randomFill,
): <T extends ArrayBufferView | ArrayBufferLike>(
buffer: T,
offset?: number,
size?: number,
) => Promise<T>;
export function promisify(fn: typeof import("node:crypto").randomInt): {
(max: number): Promise<number>;
(min: number, max: number): Promise<number>;
};
export function promisify(
fn: typeof import("node:crypto").generateKey,
): (
type: "hmac" | "aes",
options: { length: number },
) => Promise<import("node:crypto").KeyObject>;
/* dns.lookup's promise settles with { address, family } (the address
* array with options.all), and lookupService's with { hostname, service }. */
export function promisify(fn: typeof import("node:dns").lookup): {
(
hostname: string,
options: import("node:dns").LookupAllOptions,
): Promise<import("node:dns").LookupAddress[]>;
(
hostname: string,
options?: number | import("node:dns").LookupOneOptions,
): Promise<import("node:dns").LookupAddress>;
};
export function promisify(
fn: typeof import("node:dns").lookupService,
): (address: string, port: number) => Promise<{ hostname: string; service: string }>;
/* Declared surface without full lowering (the type-level tolerance
* story: guarded/diagnostic-path code must TYPECHECK; a reached use
* without a lowering fences at its site). */
export interface InspectOptions {
showHidden?: boolean | undefined;
depth?: number | null | undefined;
colors?: boolean | undefined;
customInspect?: boolean | undefined;
showProxy?: boolean | undefined;
maxArrayLength?: number | null | undefined;
maxStringLength?: number | null | undefined;
breakLength?: number | undefined;
compact?: boolean | number | undefined;
sorted?: boolean | ((a: string, b: string) => number) | undefined;
getters?: "get" | "set" | boolean | undefined;
numericSeparator?: boolean | undefined;
}
export type Style =
| "special"
| "number"
| "bigint"
| "boolean"
| "undefined"
| "null"
| "string"
| "symbol"
| "date"
| "regexp"
| "module";
export interface InspectOptionsStylized extends InspectOptions {
stylize(text: string, styleType: Style): string;
}
export type CustomInspectFunction = (
depth: number,
options: InspectOptionsStylized,
inspect: typeof import("node:util").inspect,
) => any;
export function inspect(
object: unknown,
showHidden?: boolean,
depth?: number | null,
color?: boolean,
): string;
export function inspect(object: unknown, options?: InspectOptions): string;
export namespace inspect {
/* The key of an object's custom inspect function:
* Symbol.for('nodejs.util.inspect.custom'). */
const custom: unique symbol;
}
export function format(format?: unknown, ...args: unknown[]): string;
export function formatWithOptions(
inspectOptions: InspectOptions,
format?: unknown,
...args: unknown[]
): string;
export type ParseArgsOptionsType = "boolean" | "string";
export interface ParseArgsOptionDescriptor {
type: ParseArgsOptionsType;
multiple?: boolean;
short?: string;
default?: string | boolean | string[] | boolean[];
}
export interface ParseArgsOptionsConfig {
[longOption: string]: ParseArgsOptionDescriptor;
}
export interface ParseArgsConfig {
args?: readonly string[];
options?: ParseArgsOptionsConfig;
strict?: boolean;
allowPositionals?: boolean;
allowNegative?: boolean;
tokens?: boolean;
}
export type ParseArgsToken =
| {
kind: "option";
index: number;
name: string;
rawName: string;
value: string | undefined;
inlineValue: boolean | undefined;
}
| { kind: "positional"; index: number; value: string }
| { kind: "option-terminator"; index: number };
export interface ParseArgsResult {
values: { [longOption: string]: undefined | string | boolean | Array<string | boolean> };
positionals: string[];
tokens?: ParseArgsToken[];
}
export function parseArgs(config?: ParseArgsConfig): ParseArgsResult;
/* util.getCallSites (Node ≥22.9): the captured-frame slice harness
* code reads. No stack bookkeeping exists in a compiled binary — every
* reached call fences per site. */
export interface CallSite {
readonly functionName: string;
readonly scriptName: string;
readonly lineNumber: number;
readonly column: number;
}
export function getCallSites(frameCount?: number): CallSite[];
}
declare module "node:util" {
export * from "util";
}
+43
View File
@@ -0,0 +1,43 @@
/* node:v8 — importable for the packages that require it at top level.
* getHeapStatistics answers allocator-derived figures in Node's shape
* (approximate: the runtime heap's total and used bytes, the machine's
* memory as the limit; V8-only figures are 0). The other members observe
* V8 itself and fence at their use with the by-design reason; they are
* declared so programs that type-check under their own tsc reach that
* fence. */
declare module "v8" {
type DoesZapCodeSpaceFlag = 0 | 1;
export interface HeapInfo {
total_heap_size: number;
total_heap_size_executable: number;
total_physical_size: number;
total_available_size: number;
used_heap_size: number;
heap_size_limit: number;
malloced_memory: number;
peak_malloced_memory: number;
does_zap_garbage: DoesZapCodeSpaceFlag;
number_of_native_contexts: number;
number_of_detached_contexts: number;
total_global_handles_size: number;
used_global_handles_size: number;
external_memory: number;
}
export function getHeapStatistics(): HeapInfo;
export function cachedDataVersionTag(): number;
export function getHeapSpaceStatistics(): unknown[];
export function getHeapCodeStatistics(): unknown;
export function getHeapSnapshot(options?: unknown): unknown;
export function writeHeapSnapshot(fileName?: string, options?: unknown): string;
export function setFlagsFromString(flags: string): void;
export function setHeapSnapshotNearHeapLimit(limit: number): void;
export function serialize(value: unknown): Buffer;
export function deserialize(buffer: Uint8Array): unknown;
export function takeCoverage(): void;
export function stopCoverage(): void;
export function isStringOneByteRepresentation(content: string): boolean;
}
declare module "node:v8" {
export * from "v8";
}
@@ -0,0 +1,113 @@
/// <reference path="./stream.d.ts" />
/* node:worker_threads — native workers use statically compiled entry points.
* Lowering and runtime diagnostics define the supported options and methods. */
declare module "worker_threads" {
export const isMainThread: boolean;
export const isInternalThread: boolean;
export const threadId: number;
export interface ResourceLimits {
maxYoungGenerationSizeMb?: number;
maxOldGenerationSizeMb?: number;
codeRangeSizeMb?: number;
stackSizeMb?: number;
}
/* {} in the main thread */
export const resourceLimits: ResourceLimits;
/* the Worker's name option, trimmed ("WorkerThread" by default); "" in the main thread */
export const threadName: string | null;
export interface WorkerOptions {
workerData?: unknown;
transferList?: readonly unknown[];
argv?: readonly unknown[];
name?: string;
resourceLimits?: ResourceLimits;
stdout?: boolean;
stderr?: boolean;
stdin?: boolean;
[option: string]: unknown;
}
export class Worker {
constructor(filename: string | URL, options?: WorkerOptions);
readonly threadId: number;
readonly resourceLimits?: ResourceLimits;
readonly threadName: string | null;
/* with the stdout/stderr options: the worker's writes to those streams */
readonly stdout: import("stream").Readable;
readonly stderr: import("stream").Readable;
/* with the stdin option: what the worker reads from process.stdin */
readonly stdin: import("stream").Writable | null;
/* terminate(), resolving with undefined once the worker exited */
[Symbol.asyncDispose](): Promise<void>;
on(event: "online", listener: () => void): this;
on(event: "message", listener: (value: any) => void): this;
on(event: "error", listener: (error: any) => void): this;
on(event: "exit", listener: (code: number) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
off(event: string, listener: (...args: any[]) => void): this;
addListener(event: string, listener: (...args: any[]) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
postMessage(value: unknown, transferList?: readonly unknown[]): void;
ref(): void;
unref(): void;
terminate(): Promise<number>;
removeAllListeners(event?: string): this;
listenerCount(event: string, listener?: (...args: any[]) => void): number;
}
export class MessagePort {
on(event: "message", listener: (value: any) => void): this;
on(event: "close", listener: () => void): this;
on(event: string, listener: (...args: any[]) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
off(event: string, listener: (...args: any[]) => void): this;
addListener(event: string, listener: (...args: any[]) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
postMessage(value: unknown, transferList?: readonly unknown[]): void;
start(): void;
close(callback?: () => void): void;
ref(): void;
unref(): void;
hasRef(): boolean;
removeAllListeners(event?: string): this;
listenerCount(event: string, listener?: (...args: any[]) => void): number;
}
/* Two entangled ports; a port moves to another thread through a
* postMessage or workerData transferList. */
export class MessageChannel {
readonly port1: MessagePort;
readonly port2: MessagePort;
}
export function receiveMessageOnPort(port: MessagePort): { message: any } | undefined;
/* This thread's environment data; each new Worker starts from a clone. */
export function setEnvironmentData(key: any, value?: any): void;
export function getEnvironmentData(key: any): any;
/* A marked object cannot be listed in a transfer list. */
export function markAsUntransferable(object: any): void;
/* structuredClone and postMessage throw DataCloneError for a marked
* object, error or class instance */
export function markAsUncloneable(object: any): void;
export function isMarkedAsUntransferable(object: any): boolean;
/* Delivers each message to every other open channel with the name, in
* any thread, as a 'message' MessageEvent. */
export class BroadcastChannel extends EventTarget {
constructor(name: string);
readonly name: string;
onmessage: ((event: MessageEvent) => void) | null;
onmessageerror: ((event: MessageEvent) => void) | null;
postMessage(message: unknown): void;
close(): void;
ref(): this;
unref(): this;
}
export const parentPort: MessagePort | null;
export const workerData: any;
}
declare module "node:worker_threads" {
export * from "worker_threads";
}
+422
View File
@@ -0,0 +1,422 @@
/// <reference path="./stream.d.ts" />
/* node:zlib — the one-shot zlib/raw/gzip codecs lower for string/Buffer
* inputs with Node's default options; libz links only into zlib-using
* binaries. Callback forms use the executable worker pool. Options stay
* declared so reached uses receive a named SC2020 refusal. The Deflate,
* Inflate, Gzip, Gunzip, DeflateRaw, InflateRaw, Unzip, BrotliCompress
* and BrotliDecompress streams are runtime Transform streams; Zstd remains
* outside the lowered surface. */
declare module "zlib" {
import { Transform } from "stream";
export interface ZlibOptions {
[option: string]: unknown;
}
export type ZlibCallback = (error: NodeJS.ErrnoException | null, result: Buffer) => void;
export function deflate(data: string | Uint8Array, callback: ZlibCallback): void;
export function deflate(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function deflateSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function inflate(data: string | Uint8Array, callback: ZlibCallback): void;
export function inflate(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function inflateSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function deflateRaw(data: string | Uint8Array, callback: ZlibCallback): void;
export function deflateRaw(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function deflateRawSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function inflateRaw(data: string | Uint8Array, callback: ZlibCallback): void;
export function inflateRaw(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function inflateRawSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function gzip(data: string | Uint8Array, callback: ZlibCallback): void;
export function gzip(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function gzipSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function gunzip(data: string | Uint8Array, callback: ZlibCallback): void;
export function gunzip(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function gunzipSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function unzip(data: string | Uint8Array, callback: ZlibCallback): void;
export function unzip(
data: string | Uint8Array,
options: ZlibOptions,
callback: ZlibCallback,
): void;
export function unzipSync(data: string | Uint8Array, options?: ZlibOptions): Buffer;
export function crc32(data: string | Uint8Array, value?: number): number;
/* Brotli over the vendored brotli 1.2.0 (scr_brotli.c): `params` keys
* are the numeric BROTLI_PARAM_* and BROTLI_DECODER_PARAM_* constants. */
export interface BrotliOptions {
[option: string]: unknown;
}
export function brotliCompress(data: string | Uint8Array, callback: ZlibCallback): void;
export function brotliCompress(
data: string | Uint8Array,
options: BrotliOptions,
callback: ZlibCallback,
): void;
export function brotliCompressSync(data: string | Uint8Array, options?: BrotliOptions): Buffer;
export function brotliDecompress(data: string | Uint8Array, callback: ZlibCallback): void;
export function brotliDecompress(
data: string | Uint8Array,
options: BrotliOptions,
callback: ZlibCallback,
): void;
export function brotliDecompressSync(data: string | Uint8Array, options?: BrotliOptions): Buffer;
/* The stream classes: runtime Transform streams over the zlib engine
* (scr_zlib_stream.c). createGzip(options) and new Gzip(options) build
* the same stream; options are validated at runtime with Node's rules.
* Brotli streams have no params(), as in Node. */
class ZlibBase extends Transform {
readonly bytesWritten: number;
flush(kind?: number, callback?: () => void): void;
flush(callback: () => void): void;
close(callback?: () => void): void;
reset(): void;
}
class Zlib extends ZlibBase {
params(level: number, strategy: number, callback?: () => void): void;
}
export class BrotliCompress extends ZlibBase {
constructor(options?: BrotliOptions);
}
export class BrotliDecompress extends ZlibBase {
constructor(options?: BrotliOptions);
}
export function createBrotliCompress(options?: BrotliOptions): BrotliCompress;
export function createBrotliDecompress(options?: BrotliOptions): BrotliDecompress;
export class Deflate extends Zlib {
constructor(options?: ZlibOptions);
}
export class Inflate extends Zlib {
constructor(options?: ZlibOptions);
}
export class Gzip extends Zlib {
constructor(options?: ZlibOptions);
}
export class Gunzip extends Zlib {
constructor(options?: ZlibOptions);
}
export class DeflateRaw extends Zlib {
constructor(options?: ZlibOptions);
}
export class InflateRaw extends Zlib {
constructor(options?: ZlibOptions);
}
export class Unzip extends Zlib {
constructor(options?: ZlibOptions);
}
export function createDeflate(options?: ZlibOptions): Deflate;
export function createInflate(options?: ZlibOptions): Inflate;
export function createGzip(options?: ZlibOptions): Gzip;
export function createGunzip(options?: ZlibOptions): Gunzip;
export function createDeflateRaw(options?: ZlibOptions): DeflateRaw;
export function createInflateRaw(options?: ZlibOptions): InflateRaw;
export function createUnzip(options?: ZlibOptions): Unzip;
/* Node v24 zlib.constants, literal-typed (the CryptoConstants stance):
* every access bakes as its literal; the object never materializes. The
* members outside BROTLI_* are also module properties (zlib.Z_SYNC_FLUSH). */
export interface ZlibConstants {
readonly Z_NO_FLUSH: 0;
readonly Z_PARTIAL_FLUSH: 1;
readonly Z_SYNC_FLUSH: 2;
readonly Z_FULL_FLUSH: 3;
readonly Z_FINISH: 4;
readonly Z_BLOCK: 5;
readonly Z_OK: 0;
readonly Z_STREAM_END: 1;
readonly Z_NEED_DICT: 2;
readonly Z_ERRNO: -1;
readonly Z_STREAM_ERROR: -2;
readonly Z_DATA_ERROR: -3;
readonly Z_MEM_ERROR: -4;
readonly Z_BUF_ERROR: -5;
readonly Z_VERSION_ERROR: -6;
readonly Z_NO_COMPRESSION: 0;
readonly Z_BEST_SPEED: 1;
readonly Z_BEST_COMPRESSION: 9;
readonly Z_DEFAULT_COMPRESSION: -1;
readonly Z_FILTERED: 1;
readonly Z_HUFFMAN_ONLY: 2;
readonly Z_RLE: 3;
readonly Z_FIXED: 4;
readonly Z_DEFAULT_STRATEGY: 0;
readonly ZLIB_VERNUM: 4897;
readonly DEFLATE: 1;
readonly INFLATE: 2;
readonly GZIP: 3;
readonly GUNZIP: 4;
readonly DEFLATERAW: 5;
readonly INFLATERAW: 6;
readonly UNZIP: 7;
readonly BROTLI_DECODE: 8;
readonly BROTLI_ENCODE: 9;
readonly ZSTD_DECOMPRESS: 11;
readonly ZSTD_COMPRESS: 10;
readonly Z_MIN_WINDOWBITS: 8;
readonly Z_MAX_WINDOWBITS: 15;
readonly Z_DEFAULT_WINDOWBITS: 15;
readonly Z_MIN_CHUNK: 64;
readonly Z_MAX_CHUNK: number;
readonly Z_DEFAULT_CHUNK: 16384;
readonly Z_MIN_MEMLEVEL: 1;
readonly Z_MAX_MEMLEVEL: 9;
readonly Z_DEFAULT_MEMLEVEL: 8;
readonly Z_MIN_LEVEL: -1;
readonly Z_MAX_LEVEL: 9;
readonly Z_DEFAULT_LEVEL: -1;
readonly BROTLI_OPERATION_PROCESS: 0;
readonly BROTLI_OPERATION_FLUSH: 1;
readonly BROTLI_OPERATION_FINISH: 2;
readonly BROTLI_OPERATION_EMIT_METADATA: 3;
readonly BROTLI_PARAM_MODE: 0;
readonly BROTLI_MODE_GENERIC: 0;
readonly BROTLI_MODE_TEXT: 1;
readonly BROTLI_MODE_FONT: 2;
readonly BROTLI_DEFAULT_MODE: 0;
readonly BROTLI_PARAM_QUALITY: 1;
readonly BROTLI_MIN_QUALITY: 0;
readonly BROTLI_MAX_QUALITY: 11;
readonly BROTLI_DEFAULT_QUALITY: 11;
readonly BROTLI_PARAM_LGWIN: 2;
readonly BROTLI_MIN_WINDOW_BITS: 10;
readonly BROTLI_MAX_WINDOW_BITS: 24;
readonly BROTLI_LARGE_MAX_WINDOW_BITS: 30;
readonly BROTLI_DEFAULT_WINDOW: 22;
readonly BROTLI_PARAM_LGBLOCK: 3;
readonly BROTLI_MIN_INPUT_BLOCK_BITS: 16;
readonly BROTLI_MAX_INPUT_BLOCK_BITS: 24;
readonly BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: 4;
readonly BROTLI_PARAM_SIZE_HINT: 5;
readonly BROTLI_PARAM_LARGE_WINDOW: 6;
readonly BROTLI_PARAM_NPOSTFIX: 7;
readonly BROTLI_PARAM_NDIRECT: 8;
readonly BROTLI_DECODER_RESULT_ERROR: 0;
readonly BROTLI_DECODER_RESULT_SUCCESS: 1;
readonly BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: 2;
readonly BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: 3;
readonly BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: 0;
readonly BROTLI_DECODER_PARAM_LARGE_WINDOW: 1;
readonly BROTLI_DECODER_NO_ERROR: 0;
readonly BROTLI_DECODER_SUCCESS: 1;
readonly BROTLI_DECODER_NEEDS_MORE_INPUT: 2;
readonly BROTLI_DECODER_NEEDS_MORE_OUTPUT: 3;
readonly BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: -1;
readonly BROTLI_DECODER_ERROR_FORMAT_RESERVED: -2;
readonly BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: -3;
readonly BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: -4;
readonly BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: -5;
readonly BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: -6;
readonly BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: -7;
readonly BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: -8;
readonly BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: -9;
readonly BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: -10;
readonly BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: -11;
readonly BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: -12;
readonly BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: -13;
readonly BROTLI_DECODER_ERROR_FORMAT_PADDING_1: -14;
readonly BROTLI_DECODER_ERROR_FORMAT_PADDING_2: -15;
readonly BROTLI_DECODER_ERROR_FORMAT_DISTANCE: -16;
readonly BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: -19;
readonly BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: -20;
readonly BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: -21;
readonly BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: -22;
readonly BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: -25;
readonly BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: -26;
readonly BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: -27;
readonly BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: -30;
readonly BROTLI_DECODER_ERROR_UNREACHABLE: -31;
readonly ZSTD_e_continue: 0;
readonly ZSTD_e_flush: 1;
readonly ZSTD_e_end: 2;
readonly ZSTD_fast: 1;
readonly ZSTD_dfast: 2;
readonly ZSTD_greedy: 3;
readonly ZSTD_lazy: 4;
readonly ZSTD_lazy2: 5;
readonly ZSTD_btlazy2: 6;
readonly ZSTD_btopt: 7;
readonly ZSTD_btultra: 8;
readonly ZSTD_btultra2: 9;
readonly ZSTD_c_compressionLevel: 100;
readonly ZSTD_c_windowLog: 101;
readonly ZSTD_c_hashLog: 102;
readonly ZSTD_c_chainLog: 103;
readonly ZSTD_c_searchLog: 104;
readonly ZSTD_c_minMatch: 105;
readonly ZSTD_c_targetLength: 106;
readonly ZSTD_c_strategy: 107;
readonly ZSTD_c_enableLongDistanceMatching: 160;
readonly ZSTD_c_ldmHashLog: 161;
readonly ZSTD_c_ldmMinMatch: 162;
readonly ZSTD_c_ldmBucketSizeLog: 163;
readonly ZSTD_c_ldmHashRateLog: 164;
readonly ZSTD_c_contentSizeFlag: 200;
readonly ZSTD_c_checksumFlag: 201;
readonly ZSTD_c_dictIDFlag: 202;
readonly ZSTD_c_nbWorkers: 400;
readonly ZSTD_c_jobSize: 401;
readonly ZSTD_c_overlapLog: 402;
readonly ZSTD_d_windowLogMax: 100;
readonly ZSTD_CLEVEL_DEFAULT: 3;
readonly ZSTD_error_no_error: 0;
readonly ZSTD_error_GENERIC: 1;
readonly ZSTD_error_prefix_unknown: 10;
readonly ZSTD_error_version_unsupported: 12;
readonly ZSTD_error_frameParameter_unsupported: 14;
readonly ZSTD_error_frameParameter_windowTooLarge: 16;
readonly ZSTD_error_corruption_detected: 20;
readonly ZSTD_error_checksum_wrong: 22;
readonly ZSTD_error_literals_headerWrong: 24;
readonly ZSTD_error_dictionary_corrupted: 30;
readonly ZSTD_error_dictionary_wrong: 32;
readonly ZSTD_error_dictionaryCreation_failed: 34;
readonly ZSTD_error_parameter_unsupported: 40;
readonly ZSTD_error_parameter_combination_unsupported: 41;
readonly ZSTD_error_parameter_outOfBound: 42;
readonly ZSTD_error_tableLog_tooLarge: 44;
readonly ZSTD_error_maxSymbolValue_tooLarge: 46;
readonly ZSTD_error_maxSymbolValue_tooSmall: 48;
readonly ZSTD_error_stabilityCondition_notRespected: 50;
readonly ZSTD_error_stage_wrong: 60;
readonly ZSTD_error_init_missing: 62;
readonly ZSTD_error_memory_allocation: 64;
readonly ZSTD_error_workSpace_tooSmall: 66;
readonly ZSTD_error_dstSize_tooSmall: 70;
readonly ZSTD_error_srcSize_wrong: 72;
readonly ZSTD_error_dstBuffer_null: 74;
readonly ZSTD_error_noForwardProgress_destFull: 80;
readonly ZSTD_error_noForwardProgress_inputEmpty: 82;
}
export const constants: ZlibConstants;
export const Z_NO_FLUSH: 0;
export const Z_PARTIAL_FLUSH: 1;
export const Z_SYNC_FLUSH: 2;
export const Z_FULL_FLUSH: 3;
export const Z_FINISH: 4;
export const Z_BLOCK: 5;
export const Z_OK: 0;
export const Z_STREAM_END: 1;
export const Z_NEED_DICT: 2;
export const Z_ERRNO: -1;
export const Z_STREAM_ERROR: -2;
export const Z_DATA_ERROR: -3;
export const Z_MEM_ERROR: -4;
export const Z_BUF_ERROR: -5;
export const Z_VERSION_ERROR: -6;
export const Z_NO_COMPRESSION: 0;
export const Z_BEST_SPEED: 1;
export const Z_BEST_COMPRESSION: 9;
export const Z_DEFAULT_COMPRESSION: -1;
export const Z_FILTERED: 1;
export const Z_HUFFMAN_ONLY: 2;
export const Z_RLE: 3;
export const Z_FIXED: 4;
export const Z_DEFAULT_STRATEGY: 0;
export const ZLIB_VERNUM: 4897;
export const DEFLATE: 1;
export const INFLATE: 2;
export const GZIP: 3;
export const GUNZIP: 4;
export const DEFLATERAW: 5;
export const INFLATERAW: 6;
export const UNZIP: 7;
export const ZSTD_DECOMPRESS: 11;
export const ZSTD_COMPRESS: 10;
export const Z_MIN_WINDOWBITS: 8;
export const Z_MAX_WINDOWBITS: 15;
export const Z_DEFAULT_WINDOWBITS: 15;
export const Z_MIN_CHUNK: 64;
export const Z_MAX_CHUNK: number;
export const Z_DEFAULT_CHUNK: 16384;
export const Z_MIN_MEMLEVEL: 1;
export const Z_MAX_MEMLEVEL: 9;
export const Z_DEFAULT_MEMLEVEL: 8;
export const Z_MIN_LEVEL: -1;
export const Z_MAX_LEVEL: 9;
export const Z_DEFAULT_LEVEL: -1;
export const ZSTD_e_continue: 0;
export const ZSTD_e_flush: 1;
export const ZSTD_e_end: 2;
export const ZSTD_fast: 1;
export const ZSTD_dfast: 2;
export const ZSTD_greedy: 3;
export const ZSTD_lazy: 4;
export const ZSTD_lazy2: 5;
export const ZSTD_btlazy2: 6;
export const ZSTD_btopt: 7;
export const ZSTD_btultra: 8;
export const ZSTD_btultra2: 9;
export const ZSTD_c_compressionLevel: 100;
export const ZSTD_c_windowLog: 101;
export const ZSTD_c_hashLog: 102;
export const ZSTD_c_chainLog: 103;
export const ZSTD_c_searchLog: 104;
export const ZSTD_c_minMatch: 105;
export const ZSTD_c_targetLength: 106;
export const ZSTD_c_strategy: 107;
export const ZSTD_c_enableLongDistanceMatching: 160;
export const ZSTD_c_ldmHashLog: 161;
export const ZSTD_c_ldmMinMatch: 162;
export const ZSTD_c_ldmBucketSizeLog: 163;
export const ZSTD_c_ldmHashRateLog: 164;
export const ZSTD_c_contentSizeFlag: 200;
export const ZSTD_c_checksumFlag: 201;
export const ZSTD_c_dictIDFlag: 202;
export const ZSTD_c_nbWorkers: 400;
export const ZSTD_c_jobSize: 401;
export const ZSTD_c_overlapLog: 402;
export const ZSTD_d_windowLogMax: 100;
export const ZSTD_CLEVEL_DEFAULT: 3;
export const ZSTD_error_no_error: 0;
export const ZSTD_error_GENERIC: 1;
export const ZSTD_error_prefix_unknown: 10;
export const ZSTD_error_version_unsupported: 12;
export const ZSTD_error_frameParameter_unsupported: 14;
export const ZSTD_error_frameParameter_windowTooLarge: 16;
export const ZSTD_error_corruption_detected: 20;
export const ZSTD_error_checksum_wrong: 22;
export const ZSTD_error_literals_headerWrong: 24;
export const ZSTD_error_dictionary_corrupted: 30;
export const ZSTD_error_dictionary_wrong: 32;
export const ZSTD_error_dictionaryCreation_failed: 34;
export const ZSTD_error_parameter_unsupported: 40;
export const ZSTD_error_parameter_combination_unsupported: 41;
export const ZSTD_error_parameter_outOfBound: 42;
export const ZSTD_error_tableLog_tooLarge: 44;
export const ZSTD_error_maxSymbolValue_tooLarge: 46;
export const ZSTD_error_maxSymbolValue_tooSmall: 48;
export const ZSTD_error_stabilityCondition_notRespected: 50;
export const ZSTD_error_stage_wrong: 60;
export const ZSTD_error_init_missing: 62;
export const ZSTD_error_memory_allocation: 64;
export const ZSTD_error_workSpace_tooSmall: 66;
export const ZSTD_error_dstSize_tooSmall: 70;
export const ZSTD_error_srcSize_wrong: 72;
export const ZSTD_error_dstBuffer_null: 74;
export const ZSTD_error_noForwardProgress_destFull: 80;
export const ZSTD_error_noForwardProgress_inputEmpty: 82;
}
declare module "node:zlib" {
export * from "zlib";
}
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More