diff --git a/scripts/clippy-loop/apply-patches.ts b/scripts/clippy-loop/apply-patches.ts deleted file mode 100644 index 3ebcaca9cc90..000000000000 --- a/scripts/clippy-loop/apply-patches.ts +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bun -// Reads workflow output JSON on stdin: [{file, approved, patch}], applies each -// approved patch with `git apply` (strict, then `--recount` fallback). Never -// uses `--unidiff-zero` or `-C1` — both silently corrupt by joining adjacent -// source lines when the agent's @@ header counts are off. - -import { spawnSync } from "node:child_process"; -import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; - -const input = readFileSync(0, "utf8"); -const results: Array<{ file: string; approved: boolean; patch: string; reviewNotes?: string }> = JSON.parse(input); - -const dir = mkdtempSync(join(tmpdir(), "clippy-patches-")); -let applied = 0; -let rejected = 0; -let failed = 0; - -for (const r of results) { - if (!r.approved || !r.patch?.trim()) { - rejected++; - if (r.reviewNotes) console.error(`[skip] ${r.file}: ${r.reviewNotes}`); - continue; - } - const patchFile = join(dir, r.file.replace(/[\\/]/g, "_") + ".patch"); - // ensure trailing newline; git apply is picky - writeFileSync(patchFile, r.patch.endsWith("\n") ? r.patch : r.patch + "\n"); - // Strict first; fall back to --recount only (recomputes @@ counts from body). - // NEVER use --unidiff-zero or -C1: both silently corrupt by joining adjacent - // source lines when the agent's @@ counts are off. - let res = spawnSync("git", ["apply", "--whitespace=nowarn", patchFile], { - cwd: process.cwd(), - encoding: "utf8", - }); - if (res.status !== 0) { - res = spawnSync("git", ["apply", "--recount", "--whitespace=nowarn", patchFile], { - cwd: process.cwd(), - encoding: "utf8", - }); - } - if (res.status === 0) { - applied++; - console.error(`[ok] ${r.file}`); - } else { - failed++; - const errText = res.stderr - ? res.stderr.toString().trim().split("\n")[0] - : (res.error?.message ?? `git apply exited with status ${res.status}`); - console.error(`[fail] ${r.file}: ${errText}`); - console.error(` patch saved at ${patchFile}`); - } -} - -console.error(`\napplied=${applied} rejected=${rejected} apply-failed=${failed}`); -process.stdout.write(JSON.stringify({ applied, rejected, failed }) + "\n"); -process.exit(failed > 0 ? 1 : 0); diff --git a/scripts/clippy-loop/collect-all-targets.sh b/scripts/clippy-loop/collect-all-targets.sh deleted file mode 100755 index adf70cdd8a7b..000000000000 --- a/scripts/clippy-loop/collect-all-targets.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash -# Collect ALL diagnostics (check errors + clippy errors + clippy warnings) across -# the host + the 5 commonly-broken targets, dedup by (file, line, code), and -# emit one merged manifest the edit-round workflow can consume. The per-file -# diag dump includes which targets each diagnostic fired on so the fixer knows -# to cfg-gate rather than delete. -set -euo pipefail -OUT="${CLIPPY_LOOP_DIR:-/tmp/clippy-loop}" -mkdir -p "$OUT" -# GNU base64 decodes with -d; BSD/macOS uses -D. Probe once. -if printf '' | base64 -d >/dev/null 2>&1; then B64D="-d"; else B64D="-D"; fi -TARGETS=( - x86_64-unknown-linux-gnu - aarch64-apple-darwin - x86_64-pc-windows-msvc - x86_64-unknown-freebsd - aarch64-linux-android - x86_64-unknown-linux-musl -) - -find src/ -name '*.rs' -exec touch {} + - -# Host clippy (errors + warnings — the deny set + default-on) -{ cargo clippy --workspace --no-deps --keep-going --message-format=json 2>/dev/null || true; } \ - | jq -c 'select(.reason=="compiler-message") | {target:"host", m:.message}' \ - > "$OUT/all.jsonl" - -# Per-target check (errors only — cross-platform cfg breakage) -for T in "${TARGETS[@]}"; do - >&2 echo "[collect] $T" - cargo check --workspace --target "$T" --keep-going --message-format=json 2>/dev/null \ - | jq -c --arg t "$T" 'select(.reason=="compiler-message" and .message.level=="error") | {target:$t, m:.message}' \ - >> "$OUT/all.jsonl" || true -done - -# Group by file. For each file, merge diagnostics from all targets and tag them. -jq -s ' - map( - . as $e - | ($e.m.spans | map(select(.is_primary))[0] // $e.m.spans[0]) as $sp - | select($sp != null and ($sp.file_name | startswith("src/"))) - | { - file: $sp.file_name, - code: ($e.m.code.code // "uncoded"), - line: $sp.line_start, - target: $e.target, - rendered: $e.m.rendered - } - ) - | group_by(.file) - | map({ - file: .[0].file, - count: (group_by(.code + (.line|tostring)) | length), - diagnostics: ( - group_by(.code + (.line|tostring)) - | map({ - code: .[0].code, - line: .[0].line, - targets: (map(.target) | unique), - rendered: .[0].rendered - }) - ) - }) - | sort_by(-.count) -' "$OUT/all.jsonl" > "$OUT/all.grouped.json" - ->&2 jq -r '"files=\(length) diags=\([.[].count]|add // 0)"' "$OUT/all.grouped.json" - -# Per-file diag dump (with target tags) + slim manifest -rm -rf "$OUT/diags" -mkdir -p "$OUT/diags" -jq -r '.[] | @base64' "$OUT/all.grouped.json" | while read -r b64; do - entry=$(echo "$b64" | base64 "$B64D") - file=$(echo "$entry" | jq -r '.file') - safe=$(echo "$file" | tr '/' '_') - echo "$entry" | jq -r ' - "# \(.count) diagnostics for \(.file)\n" + - (.diagnostics | map( - "## [\(.targets | join(", "))] \(.code) @ line \(.line)\n\(.rendered)" - ) | join("\n")) - ' > "$OUT/diags/${safe}.txt" -done - -jq -c --arg out "$OUT" '[.[] | {file, count, diagPath: ($out + "/diags/" + (.file | gsub("/";"_")) + ".txt")}]' \ - "$OUT/all.grouped.json" > "$OUT/manifest-all.json" - ->&2 echo "manifest: $OUT/manifest-all.json" -echo "$OUT/manifest-all.json" diff --git a/scripts/clippy-loop/collect-pr-comments.sh b/scripts/clippy-loop/collect-pr-comments.sh deleted file mode 100755 index 495e6f2aae81..000000000000 --- a/scripts/clippy-loop/collect-pr-comments.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -# Collects unresolved bot review comments from a PR, deduplicates by location, -# writes one .txt per file with all its comments, and emits a manifest -# compatible with edit-round.workflow.ts. -# -# Usage: collect-pr-comments.sh -# Output: $OUT/manifest-pr.json (path printed to stdout) -set -euo pipefail -PR="${1:?PR number}" -OUT="${CLIPPY_LOOP_DIR:-/tmp/clippy-loop}" -mkdir -p "$OUT/pr-diags" - -# `bun run` echoes the command line first; piping truncates large outputs at -# 64KB, so write to a file and strip in place. -bun run pr:comments "$PR" --json > "$OUT/pr-raw.txt" 2>/dev/null -sed -n '/^\[/,$p' "$OUT/pr-raw.txt" > "$OUT/pr-comments.json" - -# Filter: unresolved bot line-comments with a location, group by file, -# write one .txt per file with all comments + their bodies. -jq -r ' - [ .[] - | select(.tag == "line-comment" and .resolved != true) - | select(.user | test("claude\\[bot\\]|coderabbitai\\[bot\\]")) - | select(.location != null) - | { - file: (.location | split(":")[0]), - line: ((.location | split(":")[1]) // "?"), - body: .body, - url: .url - } - ] - | group_by(.file) - | .[] - | { file: .[0].file, count: length, comments: . } -' "$OUT/pr-comments.json" | jq -s '.' > "$OUT/pr-grouped.json" - -rm -rf "$OUT/pr-diags" -mkdir -p "$OUT/pr-diags" - -jq -r '.[].file' "$OUT/pr-grouped.json" | while read -r f; do - safe="${f//\//_}" - jq -r --arg f "$f" ' - .[] | select(.file == $f) | .comments[] | - "## review comment @ line \(.line)\n\(.url)\n\n\(.body)\n\n────────────────────\n" - ' "$OUT/pr-grouped.json" > "$OUT/pr-diags/${safe}.txt" -done - -jq -c --arg out "$OUT" '[.[] | {file, count, diagPath: ($out + "/pr-diags/" + (.file | gsub("/";"_")) + ".txt")}]' \ - "$OUT/pr-grouped.json" > "$OUT/manifest-pr.json" - ->&2 jq -r '"files=\(length) comments=\([.[].count]|add // 0)"' "$OUT/pr-grouped.json" -echo "$OUT/manifest-pr.json" diff --git a/scripts/clippy-loop/collect.sh b/scripts/clippy-loop/collect.sh deleted file mode 100755 index ec2864e9b8c8..000000000000 --- a/scripts/clippy-loop/collect.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# Runs clippy across the workspace with cap-lints=warn (so deny-level lints -# don't block downstream crates from being checked), groups diagnostics by -# file, writes per-file rendered dumps, and emits a slim manifest. -# -# Output: -# $OUT/round-$R.jsonl raw cargo json -# $OUT/round-$R.grouped.json -# $OUT/diags/*.txt per-file rendered diagnostics -# $OUT/manifest-$R.json [{file,count,diagPath}] (stdout = path to this) -set -euo pipefail -R="${1:?round number}" -OUT="${CLIPPY_LOOP_DIR:-/tmp/clippy-loop}" -mkdir -p "$OUT" - -find src/ -name '*.rs' -exec touch {} + -RUSTFLAGS="--cap-lints=warn" cargo clippy --workspace --no-deps --keep-going \ - --message-format=json 2>"$OUT/stderr-$R.log" > "$OUT/round-$R.jsonl" - -bun scripts/clippy-loop/group-by-file.ts "$OUT/round-$R.jsonl" > "$OUT/round-$R.grouped.json" -rm -rf "$OUT/diags" -bun scripts/clippy-loop/split-diags.ts "$OUT/round-$R.grouped.json" "$OUT/diags" \ - | jq -c '[.[] | {file,count,diagPath}]' > "$OUT/manifest-$R.json" - ->&2 jq -r '"files=\(length) diags=\([.[].count]|add // 0)"' "$OUT/round-$R.grouped.json" -echo "$OUT/manifest-$R.json" diff --git a/scripts/clippy-loop/de-unsafe.workflow.ts b/scripts/clippy-loop/de-unsafe.workflow.ts deleted file mode 100644 index e8a2dca8bd72..000000000000 --- a/scripts/clippy-loop/de-unsafe.workflow.ts +++ /dev/null @@ -1,107 +0,0 @@ -export const meta = { - name: "de-unsafe-pass", - description: "Convert pub unsafe fn(*mut T) → pub fn(&mut T) / NonNull", - phases: [ - { title: "Refactor", detail: "agent removes unsafe markers, changes ptr→ref" }, - { title: "Review", detail: "1 adversarial reviewer" }, - ], -}; - -const parsed = typeof args === "string" ? JSON.parse(args) : args; -const files = Array.isArray(parsed) ? parsed : parsed.files; -if (!Array.isArray(files)) throw new Error("args must yield an array of {file,count}"); - -const RESULT_SCHEMA = { - type: "object", - required: ["status", "summary", "callerEdits"], - properties: { - status: { type: "string", enum: ["fixed", "skipped", "partial"] }, - summary: { type: "string" }, - callerEdits: { - type: "array", - items: { type: "string" }, - description: "Files OUTSIDE this one that were edited (caller updates).", - }, - }, - additionalProperties: false, -}; - -const REVIEW_SCHEMA = { - type: "object", - required: ["verdict", "notes"], - properties: { - verdict: { type: "string", enum: ["ok", "revert", "fix-needed"] }, - notes: { type: "string" }, - }, - additionalProperties: false, -}; - -const FIXER = ` -You are converting \`pub unsafe fn\` back to safe \`pub fn\` by changing raw-pointer params to references in /root/bun-5. - -This PR over-applied "mark unsafe fn" to fix \`clippy::not_unsafe_ptr_arg_deref\`. The right fix is to change the param TYPE so the lint never fires. Find every \`pub unsafe fn\` in your assigned file (Grep \`^.*pub unsafe fn\` with line numbers, then Read the context). For each: - -1. **Skip if it was already \`unsafe\` on main** — only convert ones this PR added. Check: does the fn have a \`/// # Safety\` doc that was clearly machine-generated (e.g. "...must be a live pointer...", "...caller guarantees..."), and does the body have an \`unsafe { (*p).field }\` pattern? Those are the new ones. Genuine FFI \`extern "C"\`/\`#[no_mangle]\` fns that were ALREADY unsafe on main: skip. - -2. **\`pub unsafe fn foo(p: *mut T, ...)\` where the body just dereferences \`p\`:** - - Change to \`pub fn foo(p: &mut T, ...)\` (or \`&T\` if only reads). - - Delete the \`/// # Safety\` doc. - - In the body: \`unsafe { (*p).x }\` → \`p.x\`, \`unsafe { (*p).method() }\` → \`p.method()\`. - - If the body STORES \`p\` for later (assigns to a struct field, passes to a registry), use \`NonNull\` instead of \`&mut T\` (lifetime won't work). - - Update IN-FILE callers: \`unsafe { foo(ptr) }\` → \`foo(unsafe { &mut *ptr })\` if they hold a raw ptr; \`foo(x)\` if they hold a ref. Delete the now-redundant outer \`unsafe { }\`. - - Use Grep to find OUT-OF-FILE callers (\`Grep "fn_name\\(" --type rust\`). Edit those files too, listing them in \`callerEdits\`. - -3. **\`pub unsafe extern "C" fn\` / \`#[no_mangle]\` (called from C++):** - - Keep the \`*mut T\` signature (C ABI). Keep \`unsafe extern "C"\`. - - At the top of the body, convert once: \`let this = unsafe { &mut *this }; // SAFETY: C++ never passes null for \` and use \`this\` (a reference) for the rest. - - Delete any \`if this.is_null() { return ... }\` that follows — once you have \`&mut T\` it's unreachable. - - JSC types (JSCell, JSGlobalObject, CallFrame, JSObject, JSValue ptrs) are NEVER null from C++. Same for opaque handle types passed by-value-pointer. - -4. **\`*mut T\` arg used as opaque token / not dereferenced** (passed straight through to another FFI call): leave as \`*mut T\`, drop the \`unsafe\` marker, the lint shouldn't fire. - -HARD RULES: -- Use ONLY Read, Grep, Edit. NEVER Bash, cargo, git, Write. -- You MAY edit other files (callers) — list them in \`callerEdits\`. -- Do NOT add \`#[allow(...)]\`. -- Keep \`// SAFETY:\` comments that describe a GENUINE invariant (e.g. "C++ never passes null"). Delete vacuous ones. -`; - -const REVIEWER = ` -Adversarially review. Use ONLY Read and Grep. No Bash/cargo/git/Edit. - -Verify: -- Each \`pub unsafe fn\` either: (a) became \`pub fn(&T)\` with no inner \`unsafe { (*p) }\`, (b) stayed \`unsafe extern "C"\` (C++ caller) with a top-of-body \`let x = unsafe { &mut *p };\`, (c) was already unsafe on main (skip). -- No deleted null check that was actually load-bearing (Grep for the C++ caller — does it ever pass nullptr? If yes the check stays). -- All in-file and out-of-file callers updated. Grep the fn name. Any \`unsafe { fn_name(\` or \`fn_name(raw_ptr)\` left where the sig now wants \`&T\` is a "fix-needed". -- No use-after-free introduced (the \`&mut T\` lifetime must not outlive the original \`*mut T\`'s validity). - -verdict: "ok" / "revert" (broke compilation or introduced UAF) / "fix-needed" (callers missed). -`; - -const results = await pipeline( - files, - f => - agent(`Convert \`pub unsafe fn\` → \`pub fn(&T)\` in \`/root/bun-5/${f.file}\` (${f.count} fns).\n\n` + FIXER, { - label: `de-unsafe:${f.file}`, - phase: "Refactor", - schema: RESULT_SCHEMA, - }), - async (edit, f) => { - if (!edit) return { file: f.file, verdict: "skipped", notes: "fixer failed", callerEdits: [] }; - const review = await agent( - `Review the de-unsafe refactor of \`/root/bun-5/${f.file}\`.\n` + - `Fixer's summary: ${edit.summary}\n` + - `Caller files also edited: ${edit.callerEdits.join(", ") || "(none)"}\n\n` + - REVIEWER, - { label: `rev:${f.file}`, phase: "Review", schema: REVIEW_SCHEMA }, - ); - return { - file: f.file, - verdict: review?.verdict ?? "skipped", - notes: review?.notes ?? "", - callerEdits: edit.callerEdits, - }; - }, -); - -return results.filter(Boolean); diff --git a/scripts/clippy-loop/edit-round.workflow.ts b/scripts/clippy-loop/edit-round.workflow.ts deleted file mode 100644 index e6075da30a04..000000000000 --- a/scripts/clippy-loop/edit-round.workflow.ts +++ /dev/null @@ -1,119 +0,0 @@ -export const meta = { - name: "dead-code-edit-round", - description: "Per-file direct-edit dead-code fixer + 1-reviewer gate", - phases: [ - { title: "Edit", detail: "agent edits one file directly (no cargo/git/cross-file)" }, - { title: "Review", detail: "1 adversarial reviewer reads the diff" }, - ], -}; - -// args: Array<{file,count,diagPath}> or {files:[...]} or JSON string of either -const parsed = typeof args === "string" ? JSON.parse(args) : args; -const files = Array.isArray(parsed) ? parsed : parsed.files; -if (!Array.isArray(files)) throw new Error("args must yield an array of {file,count,diagPath}"); - -const RESULT_SCHEMA = { - type: "object", - required: ["status", "summary"], - properties: { - status: { type: "string", enum: ["fixed", "skipped", "partial"] }, - summary: { type: "string" }, - }, - additionalProperties: false, -}; - -const REVIEW_SCHEMA = { - type: "object", - required: ["verdict", "notes"], - properties: { - verdict: { type: "string", enum: ["ok", "revert", "fix-needed"] }, - notes: { type: "string" }, - }, - additionalProperties: false, -}; - -const FIXER = ` -You are fixing dead-code/unused-* lints in ONE file in the Bun repo (/root/bun-5). - -HARD RULES: -- Use ONLY Read, Grep, Edit. NEVER Bash, cargo, git, Write (use Edit for changes). -- Edit ONLY the file you are assigned. Do not touch any other file. -- Do NOT add #[allow(...)] (except: prefix a never-read field with _ on a #[repr(C)] struct). -- Do NOT change pub fn signatures (callers are in other files). - -For each diagnostic: -- unused_imports: delete the import (or just the unused names from a use {a,b,c} group). If a trait import looks unused but provides methods (Grep for .method_name in this file), keep it as \`use X as _;\`. -- dead_code (fn/struct/const/static/type/trait/field never used): Grep the name across src/ first. If 0 hits outside this file, DELETE it. If it's #[no_mangle]/extern/used in a .classes.ts/macro, prefix with _ or note in summary. Never-read field on #[repr(C)]: prefix _. -- unused_variables / unused_mut: prefix _ or remove mut. -- unused_assignments: delete the dead initializer if all paths reassign before read; otherwise delete the trailing dead write. -- unreachable_code/patterns: delete the dead arm/statement. If reachable on another platform via #[cfg], wrap in matching cfg instead. -- unused_macros: delete the macro. -- unused_doc_comments: change /// to //. - -CROSS-PLATFORM: each diagnostic in the dump is tagged \`[target1, target2, ...]\`. If a diagnostic only fires on non-host targets (e.g. \`[x86_64-pc-windows-msvc]\`), the item is USED on linux but unused/missing on that target — \`#[cfg(...)]\`-gate instead of deleting. If it fires on \`[host]\` AND a non-host target says "cannot find X" for the same name, the item is used only on that other target — \`#[cfg(that_target)]\`-gate the item. - -Clippy lints: -- not_unsafe_ptr_arg_deref: NEVER mark \`pub unsafe fn\`. Instead change the param type: - * \`*mut T\` → \`&mut T\` (or \`*const T\` → \`&T\`) when the body only ever dereferences (most cases). Update IN-FILE callers: \`foo(ptr)\` → \`foo(unsafe { &mut *ptr })\` if they hold a raw ptr, or just \`foo(x)\` if they already have a reference. If they hold \`NonNull\`, use \`.as_mut()\`/\`.as_ref()\`. - * \`*mut T\` → \`NonNull\` when the fn stores the pointer for later (callbacks, registries) — then deref sites become \`unsafe { ptr.as_mut() }\` (smaller \`unsafe\` than the whole fn). - * If the fn is \`#[no_mangle]\` / \`extern "C"\` (called from C++), keep \`*mut T\` in the signature but immediately convert at the top: \`let this = unsafe { &mut *this };\` with one \`// SAFETY: C++ guarantees non-null\` comment, then use \`this\` (a \`&mut\`) for the rest of the body. JSC objects (JSCell, JSGlobalObject, CallFrame, JSValue, etc.) are NEVER null from C++. - * Delete dead \`if ptr.is_null() { return ... }\` checks that follow — once the param is \`&T\`, the null branch is unreachable. - * **Opaque-token forwarding wrapper** (the body NEVER dereferences the pointer in Rust — it just passes it straight to an \`unsafe extern { fn ... }\` call): this is a clippy false positive. Add \`#[allow(clippy::not_unsafe_ptr_arg_deref)]\` on the fn (or impl block if multiple) with a one-line comment: \`// Forwards to C++ without dereferencing; not_unsafe_ptr_arg_deref is a false positive on opaque-token forwarding.\` -- mut_from_ref: do NOT change the signature. Add \`#[allow(clippy::mut_from_ref)]\` ONLY if the body goes through a raw pointer / UnsafeCell (note in summary). Otherwise skip. -- derivable_impls: replace the manual impl with \`#[derive(Default)]\` (or whichever trait) on the type. -- drop_non_drop: delete the \`drop(x)\` call (it's a no-op on a Copy type). -- large_enum_variant: only \`Box\` the large arm if the enum is private to this file AND every construction + match site is IN THIS FILE (you can update all of them). Otherwise — the enum is \`pub\`/\`pub(crate)\`, is an ABI type (matches a Zig union, has \`#[repr(C)]\`), or has *any* out-of-file usage — add \`#[allow(clippy::large_enum_variant)]\` with a one-line comment explaining why boxing isn't viable. This workflow edits one file at a time; boxing a variant with even one external use site breaks the build. -- vec_box: if the doc/comment says addresses must be stable across realloc (HiveArray/intrusive-list pattern), skip and note WHY. Otherwise change \`Vec>\` → \`Vec\` and remove \`Box::new\` at push sites. -- boxed_local: change \`fn foo(x: Box)\` → \`fn foo(x: T)\` and update IN-FILE callers (drop \`Box::new\`). If trait method with default body that re-boxes, change both. -- arc_with_non_send_sync: if the type is genuinely thread-safe (refcount/atomic-backed, or the Zig original was thread-shared), add \`unsafe impl Send for T {}\` + \`unsafe impl Sync for T {}\` with a \`// SAFETY:\` comment explaining why. Otherwise change \`Arc\` → \`Rc\`. -- write_with_newline: \`write!(w, "...\\n", ...)\` → \`writeln!(w, "...", ...)\` (drop the trailing \\n from the format string). -- needless_borrow / needless_borrows_for_generic_args / unnecessary_mut_passed / clone_on_copy / useless_asref / unnecessary_sort_by: apply clippy's verbatim suggestion. -- manual_c_str_literals: \`b"...\\0"\` → \`c"..."\`. -- unnecessary_unwrap / clone_on_copy / useless_conversion / redundant_locals / ptr_eq / precedence / implicit_saturating_sub / manual_swap / mem_replace_option_with_none / question_mark / needless_borrow / redundant_closure / manual_is_ascii_check / unwrap_or_default / write_with_newline / unnecessary_cast / redundant_pattern_matching / match_like_matches_macro / extra_unused_type_parameters / for_kv_map / manual_find / field_reassign_with_default / never_loop / redundant_guards / multiple_bound_locations / needless_maybe_sized / assertions_on_constants / needless_borrows_for_generic_args: apply clippy's suggested rewrite verbatim. -- vec_init_then_push: replace \`let mut v = Vec::new(); v.push(a); v.push(b);\` with \`let v = vec![a, b];\`. -- E0308/E0277/E0425 etc. (compile errors from cross-platform or autofix damage): READ the error message and surrounding code; the fix is usually wrap in \`unsafe { }\`, add \`Box::new(...)\`, restore a deleted \`mut\`, or cfg-gate. -- unused_unsafe: delete the inner \`unsafe { }\` (the call inside is now safe, or there's an outer block). -- disallowed_types/methods/macros: replace with the bun_* equivalent named in the lint reason. If this file IS the bun_* wrapper, skip. - -Prefer DELETING over gating. Be surgical. -`; - -const REVIEWER = ` -Adversarially review the edit. Use ONLY Read and Grep. No Bash/cargo/git/Edit. - -Read /root/bun-5/ as it is NOW (post-edit). Compare against the diagnostics. - -verdict: -- "ok" — every change addresses a listed diagnostic, nothing over-deleted, compiles by inspection. -- "revert" — agent broke something (deleted a used item, syntax error, removed a needed trait import). Be specific in notes. -- "fix-needed" — partially correct but left obvious issues; describe what. - -Check specifically: -- Any deleted fn/struct/const: Grep its name in src/ — if hits exist outside this file, that's a "revert". -- Any removed import that provides trait methods used in this file: "revert". -`; - -const results = await pipeline( - files, - f => - agent( - `Fix the ${f.count} dead-code/unused diagnostics in \`/root/bun-5/${f.file}\`.\n` + - `FIRST Read the diagnostics at \`${f.diagPath}\`.\n` + - `THEN Read the file and apply fixes via Edit.\n\n` + - FIXER, - { label: `edit:${f.file}`, phase: "Edit", schema: RESULT_SCHEMA }, - ), - async (edit, f) => { - if (!edit) return { file: f.file, verdict: "skipped", notes: "fixer failed" }; - const review = await agent( - `Review the dead-code fix to \`/root/bun-5/${f.file}\`.\n` + - `Original diagnostics at \`${f.diagPath}\`.\n` + - `Fixer's summary: ${edit.summary}\n\n` + - REVIEWER, - { label: `rev:${f.file}`, phase: "Review", schema: REVIEW_SCHEMA }, - ); - return { file: f.file, verdict: review?.verdict ?? "skipped", notes: review?.notes ?? "" }; - }, -); - -return results.filter(Boolean); diff --git a/scripts/clippy-loop/fix-round.workflow.ts b/scripts/clippy-loop/fix-round.workflow.ts deleted file mode 100644 index cd7fd35ff848..000000000000 --- a/scripts/clippy-loop/fix-round.workflow.ts +++ /dev/null @@ -1,158 +0,0 @@ -export const meta = { - name: "clippy-fix-round", - description: "Per-file clippy fixer with 2-reviewer adversarial gate", - phases: [ - { title: "Fix", detail: "one read-only agent per file produces a unified diff" }, - { title: "Review", detail: "2 adversarial reviewers per diff; both must approve" }, - ], -}; - -// args: Array<{file, count, diagPath}> (or {files: [...]}, or a JSON string of either) -const parsed = typeof args === "string" ? JSON.parse(args) : args; -const files = Array.isArray(parsed) ? parsed : parsed.files; -if (!Array.isArray(files)) throw new Error("args must be an array of {file,count,diagPath}"); -log(`round: ${files.length} files`); - -const PATCH_SCHEMA = { - type: "object", - required: ["patch", "summary"], - properties: { - patch: { - type: "string", - description: - "Unified diff (git apply compatible) against the repo root. Must use 'a/' and 'b/' headers and at least 3 lines of context. Empty string if no safe fix is possible.", - }, - summary: { type: "string", description: "One line per lint addressed, or why a lint was left alone." }, - skipped: { - type: "array", - items: { type: "string" }, - description: "Lint codes intentionally not fixed and why (one entry each).", - }, - }, - additionalProperties: false, -}; - -const REVIEW_SCHEMA = { - type: "object", - required: ["approved", "notes"], - properties: { - approved: { type: "boolean" }, - notes: { type: "string", description: "Concrete defects found, or 'ok'. Be specific: line, what's wrong, why." }, - revisedPatch: { - type: "string", - description: - "Optional: a corrected unified diff if the original had a fixable defect. Same format rules as the fixer. Omit if approved or if the only correct action is to drop the patch.", - }, - }, - additionalProperties: false, -}; - -const FIXER_RULES = ` -HARD CONSTRAINTS — violating any of these means your output is discarded: -- You may use ONLY the Read and Grep tools. You are FORBIDDEN from using Bash, Edit, Write, git, cargo, or any tool that mutates state. Do not build, do not run tests. -- Return your change ONLY as a unified diff in the structured output. Do not apply it. -- The diff MUST apply cleanly with \`git apply\` (strict, then \`--recount\` fallback) from repo root: headers \`--- a/\` / \`+++ b/\`, @@ hunks with ≥3 context lines per hunk, exact whitespace, LF line endings. -- The PRIMARY file is the one you were assigned. You MAY include hunks for OTHER files **only** when a signature you changed in the primary file has callers there (found via Grep). Never refactor unrelated code in other files. -- **NEVER add \`#[allow(...)]\`, \`#[expect(...)]\`, or any lint-silencing attribute. Fix the underlying code.** If a lint genuinely cannot be fixed without breaking semantics, return it in \`skipped\` with a one-sentence reason — the loop driver will escalate it; do not silence it. -- NEVER weaken behavior to satisfy a lint (no dropping a \`mem::forget\` without an equivalent ownership transfer; no deleting a \`drop()\` that has side effects; no changing eager→lazy eval where the eager value has observable side effects). -- NEVER add comments other than \`// SAFETY:\` justifications. -- Prefer the smallest correct diff. Do not reformat unrelated lines. - -LINT-SPECIFIC GUIDANCE: -- undocumented_unsafe_blocks: add \`// SAFETY: \` immediately above the \`unsafe {\`. State the invariant the surrounding code guarantees, not a restatement of the operation. Read enough context to be specific. -- mem_forget: convert to the structural equivalent — \`ManuallyDrop::new\` + later \`ManuallyDrop::into_inner\`/\`drop\`, or \`Box::into_raw\`/\`Arc::into_raw\`/\`Vec::into_raw_parts\` for FFI handoff, or \`Box::leak\`/\`&'static\` for process-lifetime. Preserve the exact ownership semantics. -- not_unsafe_ptr_arg_deref: mark the fn \`unsafe\` (or \`unsafe extern "C"\`). Grep for every Rust call site (\`rg 'fn_name\\('\` under \`src/\`) and wrap each in \`unsafe { ... }\` with a \`// SAFETY:\` comment in those files. C/C++ callers via \`#[no_mangle]\` need no change. If the pointer is never null/dangling by construction, prefer changing the param type to \`NonNull\` or \`&T\`/\`&mut T\` instead — that fixes the lint without making the fn unsafe. -- trivially_copy_pass_by_ref: change \`&T\` → \`T\`. Grep for callers; change \`f(&x)\` → \`f(x)\` (or \`f(*x)\` if \`x\` is itself a ref). Trait impls: only if the trait def is in this repo and you update it + all impls. -- needless_pass_by_value: change \`T\` → \`&T\` (or \`&str\`/\`&[_]\` for owned string/vec). Grep for callers; add \`&\`. Skip ONLY if the body moves out of the value or stores it (intentional sink) — note in \`skipped\` with the line that consumes it. -- large_types_passed_by_value: change \`T\` → \`&T\`; update callers. If the fn must own it (stores into self, returns it), \`Box\` instead. -- mut_from_ref: change the backing storage to \`UnsafeCell\` (or the existing \`bun_ptr::Cell\` if available) and return \`unsafe { &mut *cell.get() }\` with a \`// SAFETY:\` stating the no-alias invariant. Update field access sites in the same file. If the field lives in another file, include that hunk. -- cast_ptr_alignment: if the source buffer may be unaligned, use \`ptr.cast::()\` + \`read_unaligned()\`/\`write_unaligned()\` (or \`core::ptr::copy_nonoverlapping\` to a stack \`MaybeUninit\`). If alignment is guaranteed, keep the cast and add the guarantee to the enclosing \`// SAFETY:\`. -- or_fun_call: \`.unwrap_or(expr)\` → \`.unwrap_or_else(|| expr)\` etc. ONLY when \`expr\` allocates/computes; if \`expr\` is a const/literal/cheap-copy, this is a false positive — note in \`skipped\`. -- assigning_clones: \`*a = b.clone()\` → \`a.clone_from(&b)\` (or \`a.clone_from(b)\` if \`b\` is already a ref). -- unnecessary_unwrap: rewrite to \`if let\`/\`match\`/\`?\` per clippy's suggestion. -- clone_on_ref_ptr: \`x.clone()\` → \`Arc::clone(&x)\` / \`Rc::clone(&x)\`. -- derive_partial_eq_without_eq: add \`Eq\` to the derive **only if** every field type is \`Eq\` (no \`f32\`/\`f64\`). Otherwise skip — the lint is a false positive there. -- derivable_impls / vec_init_then_push / implicit_clone / map_clone / iter_overeager_cloned / ptr_as_ptr / ref_as_ptr / borrow_as_ptr / ptr_cast_constness / if_same_then_else / drop_non_drop: apply clippy's suggested rewrite. -- disallowed_types / disallowed_methods / disallowed_macros: replace with the \`bun_*\` equivalent named in the lint reason (e.g. \`std::sync::Mutex\` → \`bun_threading::Mutex\`, \`std::fs::read\` → \`bun_sys::file::read\`, \`println!\` → \`bun_core::output::println\`). Add the \`use\` import. If the bun_* API has a different signature, adapt the call. If the file IS the bun_* wrapper itself (e.g. \`bun_sys\`, \`bun_threading\`, \`bun_core::output\`), the std use is the implementation — skip and note. -- large_enum_variant: \`Box\` the large variant; update every construction and pattern-match site (Grep for the variant name). -- large_stack_frames: move the large local to \`Box::new\` / heap; if it's a fixed-size scratch buffer in a hot loop, switch to a reused field or \`SmallVec\` instead. -- useless_attribute / absurd_extreme_comparisons: delete the attribute / dead branch. -- todo / unimplemented: Grep for the function's callers. If unreachable in practice, replace with \`unreachable!()\` + a SAFETY-style comment. Otherwise skip and note — implementing missing functionality is out of scope. -- dbg_macro: delete the \`dbg!()\` (keep its inner expression if its value is used). -- clone_on_copy / useless_conversion / manual_swap / mem_replace_option_with_none / redundant_locals / manual_c_str_literals / precedence / implicit_saturating_sub / ptr_eq / vec_box / boxed_local: apply clippy's suggested rewrite. -- arc_with_non_send_sync: change \`Arc\` → \`Rc\` if the value never crosses threads (Grep for cross-thread sends); otherwise make \`T: Send + Sync\` (or wrap the non-Sync field in a Mutex). -- dead_code (fn/method/type/static/const/variant/field never used): DELETE it. First Grep for the name across \`src/\` to confirm zero references (sometimes used via macro/FFI symbol name). If it's \`#[no_mangle]\`/\`extern\` or referenced by a \`.classes.ts\`/codegen script, keep it and note in \`skipped\` (FFI export). For a never-read field, prefix with \`_\` if the struct is FFI-layout-pinned (\`#[repr(C)]\`), else delete the field + update constructors. -- unused_imports: delete the import (or just the unused names from a \`use {a, b, c}\` group). -- unused_variables / unused_mut: prefix with \`_\` if the binding is required (pattern match, FFI signature), else delete the binding. -- unused_assignments: delete the dead write; if it documents a state transition, note in \`skipped\`. -- unused_macros: delete the macro definition. -- unreachable_code / unreachable_patterns: delete the unreachable arm/statement. If it's a \`#[cfg]\`-gated fallthrough that's reachable on another platform, wrap it in the matching \`#[cfg]\` instead. -- non_snake_case / non_camel_case_types / non_upper_case_globals: rename to the conventional case AND update all references (Grep). If the name is FFI-pinned (\`#[no_mangle]\`, matches a C++ symbol, or appears in a \`.classes.ts\`/\`.bind.ts\`), keep the name and note in \`skipped\`. -`; - -const REVIEWER_RULES = ` -You are an ADVERSARIAL reviewer. Default stance: REJECT. Approve only if you cannot find a defect. -You may use ONLY Read and Grep. No Bash, no cargo, no git, no Edit/Write. - -REJECT if ANY of: -- The diff would not compile (type mismatch, missing import, signature change with a caller — Grep for it — left un-updated). -- The diff changes behavior (a dropped mem::forget that now double-frees; a fn made \`unsafe\` while a safe Rust caller exists un-wrapped; eager→lazy eval where the eager expr had side effects; \`Eq\` added to a type with float fields). -- The diff adds ANY \`#[allow(...)]\` / \`#[expect(...)]\` attribute. **These are forbidden.** Reject. -- The diff touches files other than the primary file for any reason OTHER than updating direct callers of a changed signature. -- A SAFETY comment is vacuous ("SAFETY: this is safe", "SAFETY: trust me") or factually wrong about the invariant. -- A \`disallowed_*\` replacement is applied inside the wrapper crate that legitimately implements it (\`bun_sys\`, \`bun_threading\`, \`bun_core::output\`, \`bun_collections\`). -- Unified-diff format is malformed: missing \`--- a/\` or \`+++ b/\` headers, hunks with <3 context lines, or context lines that don't match the file. **Do NOT reject solely on @@ line-count arithmetic** — the apply step uses \`git apply --recount\`, which recomputes counts from the body. Only reject if the hunk BODY itself is wrong (context mismatch, missing lines, tabs↔spaces drift). - -If you reject for a FIXABLE reason (typo, missing import, off-by-one context), provide \`revisedPatch\` with the corrected diff. -If you reject because the change is unsound or the lint should be skipped, leave \`revisedPatch\` empty. - -Be terse. \`notes\` is for the apply step, not a human. -`; - -const results = await pipeline( - files, - // ---- Fix ---- - f => - agent( - `Fix the clippy errors in \`${f.file}\` (Bun repo at /root/bun-5).\n\n` + - `There are ${f.count} diagnostics.\n` + - `FIRST: Read the full diagnostic dump at \`${f.diagPath}\` — it has every rendered error with line/col.\n` + - `THEN: Read \`/root/bun-5/${f.file}\` and produce the diff.\n` + - `For \`disallowed_*\` replacements, the bun_* API conventions are documented in \`/root/bun-5/src/CLAUDE.md\` — Read it if you need the exact signature.\n\n` + - FIXER_RULES, - { label: `fix:${f.file}`, phase: "Fix", schema: PATCH_SCHEMA }, - ), - // ---- Review (2 adversarial, parallel) ---- - async (fix, f) => { - if (!fix || !fix.patch?.trim()) { - return { file: f.file, approved: false, patch: "", reviewNotes: fix?.summary ?? "fixer produced no patch" }; - } - const reviewPrompt = - `Adversarially review this clippy-fix diff for \`${f.file}\` (Bun repo at /root/bun-5).\n\n` + - `The ${f.count} original diagnostics are at \`${f.diagPath}\` — Read that first.\n` + - `The current file is at \`/root/bun-5/${f.file}\` — Read the relevant regions.\n\n` + - `Proposed diff:\n\`\`\`diff\n${fix.patch}\n\`\`\`\n\n` + - `Fixer's summary: ${fix.summary}\n\n` + - REVIEWER_RULES; - const [r1, r2] = await parallel([ - () => agent(reviewPrompt, { label: `rev1:${f.file}`, phase: "Review", schema: REVIEW_SCHEMA }), - () => agent(reviewPrompt, { label: `rev2:${f.file}`, phase: "Review", schema: REVIEW_SCHEMA }), - ]); - const v1 = r1 ?? { approved: false, notes: "reviewer1 failed" }; - const v2 = r2 ?? { approved: false, notes: "reviewer2 failed" }; - // Both approve → ship fixer's patch. - if (v1.approved && v2.approved) { - return { file: f.file, approved: true, patch: fix.patch, reviewNotes: "2/2 approved" }; - } - // One reviewer offered a revision and the other approved the original → - // be conservative: drop (revisions aren't cross-reviewed this round). - // Both reject → drop. - const notes = [ - v1.approved ? "r1:ok" : `r1:REJECT ${v1.notes}`, - v2.approved ? "r2:ok" : `r2:REJECT ${v2.notes}`, - ].join(" | "); - return { file: f.file, approved: false, patch: "", reviewNotes: notes }; - }, -); - -return results.filter(Boolean); diff --git a/scripts/clippy-loop/group-by-file.ts b/scripts/clippy-loop/group-by-file.ts deleted file mode 100644 index c3c01f7a04e8..000000000000 --- a/scripts/clippy-loop/group-by-file.ts +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env bun -// Reads cargo clippy --message-format=json on stdin or argv[2], emits one JSON -// array of { file, count, diagnostics: [{code, message, line, col, rendered}] } -// sorted by count desc. Only includes lints we actually want fixed (the deny set -// in Cargo.toml + the deny-by-default correctness ones). - -import { readFileSync } from "node:fs"; - -const TARGET_LINTS = new Set([ - // ptr provenance - "clippy::ptr_as_ptr", - "clippy::ptr_cast_constness", - "clippy::ref_as_ptr", - "clippy::borrow_as_ptr", - // soundness / leaks - "clippy::undocumented_unsafe_blocks", - "clippy::not_unsafe_ptr_arg_deref", - "clippy::mem_forget", - "clippy::cast_ptr_alignment", - "clippy::transmute_ptr_to_ptr", - "clippy::as_ptr_cast_mut", - "clippy::drop_non_drop", - "clippy::uninit_vec", - // perf - "clippy::redundant_clone", - "clippy::unnecessary_to_owned", - "clippy::needless_collect", - "clippy::or_fun_call", - "clippy::assigning_clones", - "clippy::implicit_clone", - "clippy::iter_overeager_cloned", - "clippy::map_clone", - "clippy::trivially_copy_pass_by_ref", - "clippy::large_types_passed_by_value", - "clippy::large_enum_variant", - "clippy::large_stack_frames", - "clippy::vec_init_then_push", - "clippy::format_collect", - "clippy::manual_memcpy", - "clippy::needless_pass_by_value", - // clarity - "clippy::unnecessary_unwrap", - "clippy::derive_partial_eq_without_eq", - "clippy::derivable_impls", - "clippy::clone_on_ref_ptr", - "clippy::if_same_then_else", - "clippy::todo", - "clippy::unimplemented", - "clippy::dbg_macro", - // disallowed - "clippy::disallowed_methods", - "clippy::disallowed_types", - "clippy::disallowed_macros", - // deny-by-default correctness that block downstream crates - "clippy::useless_attribute", - "clippy::absurd_extreme_comparisons", - "clippy::mut_from_ref", - // round 2: clarity / perf additions - "clippy::clone_on_copy", - "clippy::useless_conversion", - "clippy::vec_box", - "clippy::boxed_local", - "clippy::arc_with_non_send_sync", - "clippy::manual_swap", - "clippy::mem_replace_option_with_none", - "clippy::redundant_locals", - "clippy::manual_c_str_literals", - "clippy::precedence", - "clippy::implicit_saturating_sub", - "clippy::ptr_eq", - // rustc lints (dead-code sweep) - "dead_code", - "unused_imports", - "unused_variables", - "unused_mut", - "unused_assignments", - "unused_macros", - "unreachable_code", - "unreachable_patterns", - "unreachable_pub", - "non_snake_case", - "non_camel_case_types", - "non_upper_case_globals", - "unused_must_use", - "unused_doc_comments", - "unused_parens", - "private_interfaces", -]); - -const input = process.argv[2] ? readFileSync(process.argv[2], "utf8") : readFileSync(0, "utf8"); - -type Diag = { code: string; message: string; line: number; col: number; rendered: string }; -const byFile = new Map(); - -for (const line of input.split("\n")) { - if (!line.startsWith("{")) continue; - let msg: any; - try { - msg = JSON.parse(line); - } catch { - continue; - } - if (msg.reason !== "compiler-message") continue; - const m = msg.message; - const code = m?.code?.code; - if (!code) continue; - // rustc emits deny-level lints with level "error"; clippy with "warning" under cap-lints - if (!TARGET_LINTS.has(code)) continue; - const primary = (m.spans ?? []).find((s: any) => s.is_primary) ?? m.spans?.[0]; - if (!primary) continue; - const file = (primary.file_name as string).replaceAll("\\", "/"); - if (!file.startsWith("src/")) continue; - const diag: Diag = { - code, - message: m.message, - line: primary.line_start, - col: primary.column_start, - rendered: m.rendered ?? "", - }; - const arr = byFile.get(file) ?? []; - // dedupe (workspace builds can emit same diag once per dependent feature set) - if (!arr.some(d => d.code === diag.code && d.line === diag.line && d.col === diag.col)) { - arr.push(diag); - } - byFile.set(file, arr); -} - -const out = [...byFile.entries()] - .map(([file, diagnostics]) => ({ file, count: diagnostics.length, diagnostics })) - .sort((a, b) => b.count - a.count); - -process.stdout.write(JSON.stringify(out, null, 2) + "\n"); diff --git a/scripts/clippy-loop/harvest.ts b/scripts/clippy-loop/harvest.ts deleted file mode 100644 index fffd5fa89f2a..000000000000 --- a/scripts/clippy-loop/harvest.ts +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env bun -// Reconstructs fix-round workflow output from a (possibly killed) run's -// transcript dir + journal. Maps each agent to its role/file via the prompt -// label embedded in the first user message, then re-applies the merge logic. -// -// Usage: bun harvest.ts > result.json -import { readFileSync, readdirSync } from "node:fs"; -import { join } from "node:path"; - -const dir = process.argv[2]; -if (!dir) { - process.stderr.write("Usage: bun harvest.ts \n"); - process.exit(1); -} -// Tolerate truncated/partial lines (e.g. from a killed run). -const journal = readFileSync(join(dir, "journal.jsonl"), "utf8") - .split("\n") - .filter(l => l.startsWith("{")) - .flatMap(l => { - try { - return [JSON.parse(l)]; - } catch { - return []; - } - }); - -const results = new Map(); -for (const e of journal) if (e.type === "result") results.set(e.agentId, e.result); - -type Role = "fix" | "rev1" | "rev2"; -const byFile = new Map>>(); - -for (const f of readdirSync(dir)) { - const m = f.match(/^agent-([a-f0-9]+)\.jsonl$/); - if (!m) continue; - const agentId = m[1]; - const first = readFileSync(join(dir, f), "utf8").split("\n", 1)[0]; - if (!first) continue; - let prompt: string; - try { - const msg = JSON.parse(first); - const content = msg.message?.content; - prompt = typeof content === "string" ? content : (content?.[0]?.text ?? content?.[0]?.content ?? ""); - } catch { - continue; - } - // The prompt starts with either: - // "Fix the clippy errors in `` ..." - // "Adversarially review this clippy-fix diff for `` ..." - const fileMatch = prompt.match(/`((?:src|test)\/[^`]+\.rs)`/); - if (!fileMatch) continue; - const file = fileMatch[1]; - let role: Role; - if (prompt.startsWith("Fix the clippy errors")) role = "fix"; - else if (prompt.startsWith("Adversarially review")) { - // rev1/rev2 share the same prompt; use arrival order - const slot = byFile.get(file); - role = slot?.rev1 === undefined ? "rev1" : "rev2"; - } else continue; - const slot = byFile.get(file) ?? {}; - slot[role] = results.get(agentId) ?? null; - byFile.set(file, slot); -} - -const out = []; -for (const [file, s] of byFile) { - const fix = s.fix; - if (!fix || !fix.patch?.trim()) { - out.push({ file, approved: false, patch: "", reviewNotes: fix?.summary ?? "fixer produced no patch" }); - continue; - } - const v1 = s.rev1 ?? { approved: false, notes: "rev1 missing" }; - const v2 = s.rev2 ?? { approved: false, notes: "rev2 missing" }; - if (v1.approved && v2.approved) { - out.push({ file, approved: true, patch: fix.patch, reviewNotes: "2/2 approved" }); - } else { - out.push({ - file, - approved: false, - patch: "", - reviewNotes: - (v1.approved ? "r1:ok" : `r1:REJECT ${v1.notes}`) + " | " + (v2.approved ? "r2:ok" : `r2:REJECT ${v2.notes}`), - }); - } -} - -process.stderr.write( - `harvested ${out.length} files: approved=${out.filter(o => o.approved).length} rejected=${out.filter(o => !o.approved).length}\n`, -); -process.stdout.write(JSON.stringify(out) + "\n"); diff --git a/scripts/clippy-loop/review-round.workflow.ts b/scripts/clippy-loop/review-round.workflow.ts deleted file mode 100644 index 7bbfb93f4d4a..000000000000 --- a/scripts/clippy-loop/review-round.workflow.ts +++ /dev/null @@ -1,94 +0,0 @@ -export const meta = { - name: "review-round", - description: "Per-file PR review-comment fixer + 1-reviewer gate", - phases: [ - { title: "Address", detail: "agent reads bot review comments and fixes the file" }, - { title: "Review", detail: "1 adversarial reviewer per file" }, - ], -}; - -const parsed = typeof args === "string" ? JSON.parse(args) : args; -const files = Array.isArray(parsed) ? parsed : parsed.files; -if (!Array.isArray(files)) throw new Error("args must yield an array of {file,count,diagPath}"); - -const VERDICT_SCHEMA = { - type: "object", - required: ["verdict", "notes"], - properties: { - verdict: { type: "string", enum: ["ok", "revert", "fix-needed", "skipped"] }, - notes: { type: "string" }, - }, - additionalProperties: false, -}; - -const ADDRESS_SCHEMA = { - type: "object", - required: ["status", "summary"], - properties: { - status: { type: "string", enum: ["fixed", "skipped", "partial"] }, - summary: { type: "string" }, - skipped: { - type: "array", - items: { type: "string" }, - description: "Comments intentionally NOT acted on, with one-line reason each.", - }, - }, - additionalProperties: false, -}; - -const FIXER = ` -You are addressing bot review comments on a Bun PR (repo at /root/bun-5). - -FIRST: Read the comment dump at the diagPath (one entry per comment, with the bot's reasoning). -THEN: Read the current file. The comments may reference an OLD commit — verify each finding is STILL present before fixing. - -For each comment: -- If the issue is already fixed (a later commit addressed it): note in \`skipped\`. -- If the bot is factually wrong (verify by reading the actual code): note in \`skipped\` with a one-line correction. -- If the bot is right and the fix is in-file: apply it via Edit. -- If the fix needs cross-file changes: apply them all (Grep for the identifier; you have full Edit access). -- If the bot suggests a refactor that's out-of-scope (architecture change, multi-crate API): note in \`skipped\` with rationale. - -HARD RULES: -- Use Read, Grep, Edit, Bash (\`cargo check -p --message-format=short\` to verify; NO \`cargo build\`, NO \`bun bd\`). Do NOT use git. -- NEVER add \`#[allow(...)]\` to a deny-level lint without a one-line comment explaining why. -- NEVER box a value that lives in a bump arena (no Drop on free → leak). -- Match the file's existing style (comment density, naming, idiom). -- After editing, run \`cargo check -p --message-format=short 2>&1 | grep ': error'\` and report. -`; - -const REVIEWER = ` -Adversarially review whether the bot review comments for this file were correctly addressed. -Use ONLY Read and Grep. No Bash/cargo/git/Edit. - -Read the comment dump at the diagPath. Read the current file. For each comment: -- Was it addressed? Or correctly skipped with a stated reason? -- Did the fix introduce a new bug? (deleted code that's used elsewhere, broken signature, etc.) -- Did the fix box an arena-allocated type? (= LSan leak) - -verdict: "ok" / "fix-needed" (something missed or fix is wrong, list what) / "skipped" (no action taken and that's correct). -`; - -const results = await pipeline( - files, - f => - agent( - `Address ${f.count} bot review comments on \`/root/bun-5/${f.file}\`.\n` + - `Comments dump: \`${f.diagPath}\` — Read this first.\n\n` + - FIXER, - { label: `review:${f.file}`, phase: "Address", schema: ADDRESS_SCHEMA }, - ), - async (edit, f) => { - if (!edit) return { file: f.file, verdict: "skipped", notes: "fixer failed" }; - const review = await agent( - `Review whether bot comments on \`/root/bun-5/${f.file}\` were addressed.\n` + - `Comments dump: \`${f.diagPath}\`. Fixer's summary: ${edit.summary}\n` + - `Fixer's skips: ${(edit.skipped || []).join(" | ")}\n\n` + - REVIEWER, - { label: `rev:${f.file}`, phase: "Review", schema: VERDICT_SCHEMA }, - ); - return { file: f.file, verdict: review?.verdict ?? "skipped", notes: review?.notes ?? "" }; - }, -); - -return results.filter(Boolean); diff --git a/scripts/clippy-loop/shard.ts b/scripts/clippy-loop/shard.ts deleted file mode 100644 index 8e4b563d80c9..000000000000 --- a/scripts/clippy-loop/shard.ts +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bun -// Splits a manifest [{file,count,diagPath}] into N interleaved shards so each -// shard gets a mix of high- and low-count files. Writes shard-.json under -// argv[4] (default /tmp/clippy-loop/shards) and prints the paths. -import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; - -const manifest = JSON.parse(readFileSync(process.argv[2], "utf8")) as Array<{ - file: string; - count: number; - diagPath: string; -}>; -const n = Number(process.argv[3]); -if (!Number.isInteger(n) || n < 1) { - console.error(`shard count must be a positive integer (got ${process.argv[3]})`); - process.exit(1); -} -const outDir = process.argv[4] || "/tmp/clippy-loop/shards"; -mkdirSync(outDir, { recursive: true }); - -const shards: (typeof manifest)[] = Array.from({ length: n }, () => []); -manifest.forEach((m, i) => shards[i % n].push(m)); - -for (let i = 0; i < n; i++) { - const p = join(outDir, `shard-${i}.json`); - writeFileSync(p, JSON.stringify(shards[i])); - const diags = shards[i].reduce((s, x) => s + x.count, 0); - console.error(`shard-${i}: ${shards[i].length} files, ${diags} diags`); - console.log(p); -} diff --git a/scripts/clippy-loop/split-diags.ts b/scripts/clippy-loop/split-diags.ts deleted file mode 100644 index fdd1ff3b50da..000000000000 --- a/scripts/clippy-loop/split-diags.ts +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bun -// Reads grouped JSON (group-by-file output) on argv[2], writes one rendered-text -// file per source file under argv[3], emits a slim manifest [{file,count,diagPath,codes}] -// on stdout. -import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; - -if (!process.argv[2] || !process.argv[3]) { - process.stderr.write("Usage: split-diags \n"); - process.exit(2); -} - -const grouped = JSON.parse(readFileSync(process.argv[2], "utf8")) as Array<{ - file: string; - count: number; - diagnostics: Array<{ code: string; line: number; col: number; rendered: string }>; -}>; -const outDir = process.argv[3]; -mkdirSync(outDir, { recursive: true }); - -const manifest = grouped.map(g => { - const safe = g.file.replace(/[\\/]/g, "__"); - const diagPath = join(outDir, safe + ".txt"); - const body = - `# ${g.count} clippy diagnostics for ${g.file}\n\n` + g.diagnostics.map(d => d.rendered.trimEnd()).join("\n\n"); - writeFileSync(diagPath, body); - const codes = [...new Set(g.diagnostics.map(d => d.code))]; - return { file: g.file, count: g.count, diagPath, codes }; -}); - -process.stdout.write(JSON.stringify(manifest) + "\n"); diff --git a/src/base64/neonbase64 b/src/base64/neonbase64 deleted file mode 100644 index 74153ebe4f85..000000000000 Binary files a/src/base64/neonbase64 and /dev/null differ diff --git a/src/bun_core/lib.rs b/src/bun_core/lib.rs index 7a6664d9e134..a83c5d96731f 100644 --- a/src/bun_core/lib.rs +++ b/src/bun_core/lib.rs @@ -1008,12 +1008,9 @@ macro_rules! enum_unwrap { }; } -/// Unwrap a `Result`, calling `outOfMemory()` on -/// `Err`. The full multi-arm version (which narrows mixed error sets) lives in -/// `bun_crash_handler::handle_oom`; that crate sits *above* `bun_core` in the -/// dep graph, so this tier-0 alias is the OOM-only arm — sufficient for the -/// `Result` / `Result` callers in `js_parser`, -/// `bake/DevServer`, etc. that spell it `bun_core::handle_oom`. +/// Unwrap a `Result`, calling `outOfMemory()` on **any** `Err`. The +/// `AllocError`-only version lives in `bun_crash_handler::handle_oom` (that +/// crate sits *above* `bun_core` in the dep graph). #[inline] #[track_caller] pub fn handle_oom(r: core::result::Result) -> T { @@ -1024,15 +1021,8 @@ pub fn handle_oom(r: core::result::Result) -> T { } /// Extension-method form of [`handle_oom`]: `.unwrap_or_oom()` on any -/// `Result`. The *loose* idiom -/// that panics on **any** `Err`, not just OOM-only error sets. For the -/// narrowing version see `bun_crash_handler::HandleOom`. -/// -/// This is intentionally a blanket `impl` — it matches the -/// existing `bun_core::handle_oom` free fn and the two pre-existing local -/// blanket impls in `run_command.rs` / `valkey.rs`. Callers that want a strict -/// `error{OutOfMemory}`-only whitelist should use `bun_crash_handler::HandleOom` -/// instead. +/// `Result`, treating **any** `Err` as OOM. For the `AllocError`-only +/// version see `bun_crash_handler::handle_oom`. pub trait UnwrapOrOom { type Output; fn unwrap_or_oom(self) -> Self::Output; diff --git a/src/collections/lib.rs b/src/collections/lib.rs index c1d84177c9ad..c35ead1abd8b 100644 --- a/src/collections/lib.rs +++ b/src/collections/lib.rs @@ -59,14 +59,6 @@ pub struct PriorityQueue { pub items: Vec, pub(crate) context: C, } -impl Default for PriorityQueue { - fn default() -> Self { - Self { - items: Vec::new(), - context: C::default(), - } - } -} impl PriorityQueue { pub fn init(context: C) -> Self { Self { diff --git a/src/crash_handler/handle_oom.rs b/src/crash_handler/handle_oom.rs index 6cac4575f436..4539f90b70fa 100644 --- a/src/crash_handler/handle_oom.rs +++ b/src/crash_handler/handle_oom.rs @@ -1,91 +1,10 @@ -use crate::Error; use bun_alloc::AllocError; -// "OOM-only" vs "other errors possible" is encoded structurally in the -// `HandleOom` trait impls below — the `AllocError` impls ARE the "OOM-only" -// arm (Output = T / Output = !), and the `crate::Error` impls ARE the -// "other errors possible" arm (Output = Result / Output = E). - -/// If `error_union_or_set` is `error.OutOfMemory`, calls `bun.outOfMemory`. Otherwise: -/// -/// * If that was the only possible error, returns the non-error payload for error unions, or -/// `noreturn` for error sets. -/// * If other errors are possible, returns the same error union or set, but without -/// `error.OutOfMemory` in the error set. -/// -/// Prefer this method over `catch bun.outOfMemory()`, since that could mistakenly catch -/// non-OOM-related errors. -/// -/// There are two ways to use this function: -/// -/// ```ignore -/// // option 1: -/// let thing = bun::handle_oom(allocate_thing()); -/// // option 2: -/// let thing = match allocate_thing() { Ok(v) => v, Err(err) => bun::handle_oom(err) }; -/// ``` -/// -/// In Rust, `Vec`/`Box` allocation already aborts on OOM via the -/// global allocator's `handle_alloc_error`. Per PORTING.md §Allocators, -/// callsites of `bun.handleOom(expr)` translate to bare `expr`. This function -/// remains for the residual cases where a `Result` is threaded -/// explicitly. -pub fn handle_oom(error_union_or_set: A) -> A::Output { - error_union_or_set.handle_oom() -} - -/// Output-type selection for [`handle_oom`]: each impl below is one arm of -/// the input-shape × OOM-only matrix (see the section comments). -pub trait HandleOom { - type Output; - fn handle_oom(self) -> Self::Output; -} - -// ── .error_union, isOomOnlyError == true → union_info.payload ──────────── -impl HandleOom for Result { - type Output = T; - fn handle_oom(self) -> T { - match self { - Ok(success) => success, - Err(AllocError) => crate::out_of_memory(), - } - } -} - -// ── .error_set, isOomOnlyError == true → noreturn ──────────────────────── -// `!` as an associated type requires nightly; use `core::convert::Infallible` -// (uninhabited) so callers can `match x {}`. -impl HandleOom for AllocError { - type Output = core::convert::Infallible; - fn handle_oom(self) -> core::convert::Infallible { - crate::out_of_memory() - } -} - -// ── .error_union, mixed error set → same union with OOM subtracted ─────── -// Rust error enums are nominal, not sets — there is no set subtraction. For -// the catch-all `crate::Error` we compare against the interned tag and -// return the same type. Per-crate `thiserror` enums that carry an -// `OutOfMemory` variant should add their own `HandleOom` impl. -impl HandleOom for Result { - type Output = Result; - fn handle_oom(self) -> Result { - match self { - Ok(success) => Ok(success), - Err(Error::Alloc(_)) => crate::out_of_memory(), - Err(other_error) => Err(other_error), - } - } -} - -// ── .error_set, mixed → same set with OOM subtracted ───────────────────── -impl HandleOom for Error { - type Output = Error; - fn handle_oom(self) -> Error { - if matches!(self, Error::Alloc(_)) { - crate::out_of_memory() - } else { - self - } +/// Unwraps a `Result`, converting OOM into the controlled +/// `bun.outOfMemory` crash. +pub fn handle_oom(result: Result) -> T { + match result { + Ok(success) => success, + Err(AllocError) => crate::out_of_memory(), } } diff --git a/src/crash_handler/lib.rs b/src/crash_handler/lib.rs index a5cb8c8966ea..da54f911aae2 100644 --- a/src/crash_handler/lib.rs +++ b/src/crash_handler/lib.rs @@ -87,7 +87,6 @@ pub mod debug { bun_core::capture_stack_trace(begin, addrs) } - pub(crate) const HAVE_ERROR_RETURN_TRACING: bool = false; #[cfg(not(any(target_os = "linux", target_os = "android")))] pub(crate) const STRIP_DEBUG_INFO: bool = !cfg!(debug_assertions); @@ -771,14 +770,12 @@ mod draft { /// Where the crash trace is seeded from. Each call site has exactly one. #[derive(Clone, Copy)] - pub enum TraceSeed<'a> { + pub enum TraceSeed { /// Signal/exception handler saved the fault register context. `pc` /// becomes frame 0. POSIX: `fp` is the saved frame-pointer register and /// the walk follows the fp chain. Windows: `fp` is the `*const CONTEXT` /// from `EXCEPTION_POINTERS` and the walk uses `RtlVirtualUnwind`. Fault { pc: usize, fp: usize }, - /// A trace was already captured upstream. - ErrorReturn(&'a StackTrace<'a>), /// Walk the current stack and trim the capture machinery above this PC. BeginAddr(usize), /// Walk the current stack with no trim (the handler's own `return_address()` @@ -788,7 +785,7 @@ mod draft { /// This function is invoked when a crash happens. A crash is classified in `CrashReason`. #[cold] - pub fn crash_handler(reason: CrashReason, seed: TraceSeed<'_>) -> ! { + pub fn crash_handler(reason: CrashReason, seed: TraceSeed) -> ! { if cfg!(debug_assertions) { Output::disable_scoped_debug_writer(); } @@ -1026,9 +1023,8 @@ mod draft { let mut addr_buf: [usize; 20] = [0; 20]; let trace_buf: StackTrace; - let trace: &StackTrace = 'blk: { + let trace: &StackTrace = { let idx: usize = match seed { - TraceSeed::ErrorReturn(ert) => break 'blk ert, // For an actual fault the signal/exception handler hands // us the saved register context. Seeding the walk from // the fault `pc`/`fp` is the only reliable way to recover @@ -1050,7 +1046,7 @@ mod draft { index: idx, instruction_addresses: &addr_buf, }; - break 'blk &trace_buf; + &trace_buf }; if debug_trace { @@ -1248,10 +1244,7 @@ mod draft { /// This is called when `main` returns an error. /// We don't want to treat it as a crash under certain error codes. #[allow(clippy::needless_pass_by_value)] - pub fn handle_root_error( - err: impl bun_core::output::ErrName, - error_return_trace: Option<&StackTrace>, - ) -> ! { + pub fn handle_root_error(err: impl bun_core::output::ErrName) -> ! { use bun_core::{err_generic, pretty_error}; /// bun_sys::posix has no rlimit yet — @@ -1268,7 +1261,6 @@ mod draft { } } - let mut show_trace = Environment::SHOW_CRASH_TRACE; let name: &[u8] = err.name(); if name == b"OutOfMemory" { @@ -1277,9 +1269,7 @@ mod draft { name, b"InvalidArgument" | b"Invalid Bunfig" | b"InstallFailed" ) { - if !show_trace { - Global::exit(1); - } + // Already printed their own diagnostics; exit quietly below. } else if name == b"SyntaxError" { Output::err("SyntaxError", "An error occurred while parsing code", ()); } else if name == b"CurrentWorkingDirectoryUnlinked" { @@ -1409,7 +1399,6 @@ mod draft { "An unknown error occurred ({})", bstr::BStr::new(name), ); - show_trace = true; } } #[cfg(not(unix))] @@ -1418,7 +1407,6 @@ mod draft { "An unknown error occurred ({})", bstr::BStr::new(name), ); - show_trace = true; } } else if matches!(name, b"ENOENT" | b"FileNotFound") { Output::err( @@ -1440,23 +1428,13 @@ mod draft { bstr::BStr::new(name) ); } - show_trace = true; - } - - if show_trace { - VERBOSE_ERROR_TRACE.store(show_trace, Ordering::Relaxed); - handle_error_return_trace_extra::(name, error_return_trace); } Global::exit(1); } #[cold] - pub fn panic_impl( - msg: &[u8], - error_return_trace: Option<&StackTrace>, - begin_addr: Option, - ) -> ! { + pub fn panic_impl(msg: &[u8], begin_addr: Option) -> ! { // Not `unwrap_or_else(debug::return_address)`: the default trim anchor // must be read from *this* function's frame. Evaluated lazily, the // `#[inline(always)]` intrinsic reads the closure's frame instead, @@ -1474,10 +1452,7 @@ mod draft { // SAFETY: process is about to abort; the borrow is never invalidated. CrashReason::Panic(unsafe { bun_collections::detach_lifetime(msg) }) }, - match error_return_trace { - Some(ert) if ert.index > 0 => TraceSeed::ErrorReturn(ert), - _ => TraceSeed::BeginAddr(begin_addr), - }, + TraceSeed::BeginAddr(begin_addr), ); } @@ -2573,26 +2548,6 @@ mod draft { } } - impl fmt::Display for StackLine { - fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result { - let addr_display: u64 = if cfg!(target_os = "macos") { - self.address as u64 + 0x100000000 - } else { - self.address as u64 - }; - write!( - writer, - "0x{:x}{}{}", - addr_display, - if self.object.is_some() { " @ " } else { "" }, - self.object - .as_deref() - .map(bstr::BStr::new) - .unwrap_or_default(), - ) - } - } - struct TraceString<'a> { trace: &'a StackTrace<'a>, reason: CrashReason, @@ -3029,85 +2984,6 @@ mod draft { } } - pub static VERBOSE_ERROR_TRACE: AtomicBool = AtomicBool::new(false); - - #[cold] - #[inline(never)] - fn cold_handle_error_return_trace(err_name: &[u8], trace: &StackTrace) { - // The format of the panic trace is slightly different in debug - // builds Mainly, we demangle the backtrace immediately instead - // of using a trace string. - // - // To make the release-mode behavior easier to demo, debug mode - // checks for this CLI flag. - let is_debug = cfg!(debug_assertions) - && 'check_flag: { - for arg in Output::argv() { - if arg == b"--debug-crash-handler-use-trace-string" { - break 'check_flag false; - } - } - true - }; - - if is_debug { - if IS_ROOT { - // SAFETY: read-only access - if VERBOSE_ERROR_TRACE.load(Ordering::Relaxed) { - bun_core::note!("Release build will not have this trace by default:"); - } - } else { - bun_core::pretty_errorln!( - "note: caught error.{}:", - bstr::BStr::new(err_name) - ); - } - Output::flush(); - dump_stack_trace(trace, WriteStackTraceLimits::default()); - } else { - // SAFETY: `err_name` outlives the local `TraceString` it is formatted through. - let reason = - CrashReason::ZigError(unsafe { bun_collections::detach_lifetime(err_name) }); - let ts = TraceString { - trace, - reason, - action: TraceStringAction::ViewTrace, - }; - if IS_ROOT { - bun_core::pretty_errorln!( - "\nTo send a redacted crash report to Bun's team,\nplease file a GitHub issue using the link below:\n\n {}\n", - ts, - ); - } else { - bun_core::pretty_errorln!( - "trace: error.{}: {}", - bstr::BStr::new(err_name), - ts, - ); - } - } - } - - #[inline] - fn handle_error_return_trace_extra( - err_name: &[u8], - maybe_trace: Option<&StackTrace>, - ) { - // Rust has no error-return tracing; `HAVE_ERROR_RETURN_TRACING` is const - // false, so this path is currently dead. - if !debug::HAVE_ERROR_RETURN_TRACING { - return; - } - // SAFETY: read-only access - if !VERBOSE_ERROR_TRACE.load(Ordering::Relaxed) && !IS_ROOT { - return; - } - - if let Some(trace) = maybe_trace { - cold_handle_error_return_trace::(err_name, trace); - } - } - unsafe extern "C" { fn WTF__DumpStackTrace(ptr: *const usize, count: usize); } @@ -3747,7 +3623,7 @@ mod draft { "unsupported uv function: {}", bstr::BStr::new(name_bytes) ); - panic_impl(msg.slice(), None, None); + panic_impl(msg.slice(), None); } /// # Safety diff --git a/src/js/bun/sql.ts b/src/js/bun/sql.ts index c3a74582a259..057788e206f9 100644 --- a/src/js/bun/sql.ts +++ b/src/js/bun/sql.ts @@ -1038,34 +1038,6 @@ SQL.PostgresError = PostgresError; SQL.SQLiteError = SQLiteError; SQL.MySQLError = MySQLError; -// // Helper functions for native code to create error instances -// // These are internal functions used by native code -// export function $createPostgresError( -// message: string, -// code: string, -// detail: string, -// hint: string, -// severity: string, -// additionalFields?: Record, -// ) { -// const options = { -// code, -// detail, -// hint, -// severity, -// ...additionalFields, -// }; -// return new PostgresError(message, options); -// } - -// export function $createSQLiteError(message: string, code: string, errno: number) { -// return new SQLiteError(message, { code, errno }); -// } - -// export function $createSQLError(message: string) { -// return new SQLError(message); -// } - export default { sql: defaultSQLObject, default: defaultSQLObject, diff --git a/src/jsc/bindings/JSDOMWrapper.h b/src/jsc/bindings/JSDOMWrapper.h index db5044a4af7a..31a2b19edf27 100644 --- a/src/jsc/bindings/JSDOMWrapper.h +++ b/src/jsc/bindings/JSDOMWrapper.h @@ -78,7 +78,6 @@ class JSDOMWrapper : public JSDOMObject { ImplementationClass& wrapped() const { return m_wrapped; } Ref protectedWrapped() const { return m_wrapped; } static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper, m_wrapped); } - constexpr static bool hasCustomPtrTraits() { return !std::is_same_v>; }; protected: JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject& globalObject, Ref&& impl) diff --git a/src/jsc/bindings/dh-primes.h b/src/jsc/bindings/dh-primes.h index 6198b870c741..a6703a49b2ed 100644 --- a/src/jsc/bindings/dh-primes.h +++ b/src/jsc/bindings/dh-primes.h @@ -59,16 +59,4 @@ #include #include -// Backporting primes that may not be supported in earlier boringssl versions. -// Intentionally keeping the existing C-style formatting. - -#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) - -#if defined(OPENSSL_64_BIT) -#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo)) -#elif defined(OPENSSL_32_BIT) -#define TOBN(hi, lo) (lo), (hi) -#else -#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" -#endif #endif // DEPS_NCRYPTO_DH_PRIMES_H_ diff --git a/src/jsc/bindings/napi.h b/src/jsc/bindings/napi.h index f7896c847b73..2b14c0531c72 100644 --- a/src/jsc/bindings/napi.h +++ b/src/jsc/bindings/napi.h @@ -156,13 +156,6 @@ static bool equal(napi_async_cleanup_hook_handle one, napi_async_cleanup_hook_ha Bun__crashHandler(message "", sizeof(message "") - 1); \ } while (0) -#define NAPI_PERISH(...) \ - do { \ - WTFReportError(__FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__); \ - WTFReportBacktrace(); \ - NAPI_ABORT("Aborted"); \ - } while (0) - #define NAPI_RELEASE_ASSERT(assertion, ...) \ do { \ if (!(assertion)) [[unlikely]] { \ diff --git a/src/jsc/bindings/node/crypto/KeyObject.h b/src/jsc/bindings/node/crypto/KeyObject.h index 132249f3569a..5855f1e2c00d 100644 --- a/src/jsc/bindings/node/crypto/KeyObject.h +++ b/src/jsc/bindings/node/crypto/KeyObject.h @@ -29,7 +29,6 @@ class KeyObject { static KeyObject create(WTF::Vector&& symmetricKey); static KeyObject create(WebCore::CryptoKeyType type, ncrypto::EVPKeyPointer&& asymmetricKey); static KeyObject create(WebCore::CryptoKeyType type, RefPtr&& data); - // static KeyObject createJwk(JSC::JSGlobalObject*, JSC::ThrowScope&, JSC::JSValue keyValue, WebCore::CryptoKeyType type); enum class KeyEncodingContext { Input, diff --git a/src/jsc/bindings/webcore/DOMConstructors.h b/src/jsc/bindings/webcore/DOMConstructors.h index 36a2fd08cc41..b993452e7f10 100644 --- a/src/jsc/bindings/webcore/DOMConstructors.h +++ b/src/jsc/bindings/webcore/DOMConstructors.h @@ -7,864 +7,65 @@ namespace WebCore { enum class DOMConstructorID : uint16_t { - Touch, - TouchEvent, - TouchList, - InternalSettingsGenerated, - GPU, - GPUAdapter, - GPUBindGroup, - GPUBindGroupLayout, - GPUBuffer, - GPUBufferUsage, - GPUCanvasContext, - GPUColorWrite, - GPUCommandBuffer, - GPUCommandEncoder, - GPUCompilationInfo, - GPUCompilationMessage, - GPUComputePassEncoder, - GPUComputePipeline, - GPUDevice, - GPUDeviceLostInfo, - GPUExternalTexture, - GPUMapMode, - GPUOutOfMemoryError, - GPUPipelineLayout, - GPUQuerySet, - GPUQueue, - GPURenderBundle, - GPURenderBundleEncoder, - GPURenderPassEncoder, - GPURenderPipeline, - GPUSampler, - GPUShaderModule, - GPUShaderStage, - GPUSupportedFeatures, - GPUSupportedLimits, - GPUTexture, - GPUTextureUsage, - GPUTextureView, - GPUUncapturedErrorEvent, - GPUValidationError, - WebKitPlaybackTargetAvailabilityEvent, - ApplePayCancelEvent, - ApplePayCouponCodeChangedEvent, - ApplePayError, - ApplePayPaymentAuthorizedEvent, - ApplePayPaymentMethodSelectedEvent, - ApplePaySession, - ApplePaySetup, - ApplePaySetupFeature, - ApplePayShippingContactSelectedEvent, - ApplePayShippingMethodSelectedEvent, - ApplePayValidateMerchantEvent, - Clipboard, - ClipboardItem, - DOMCache, - DOMCacheStorage, - ContactsManager, - BasicCredential, - CredentialsContainer, - MediaKeyMessageEvent, - MediaKeySession, - MediaKeyStatusMap, - MediaKeySystemAccess, - MediaKeys, - WebKitMediaKeyMessageEvent, - WebKitMediaKeyNeededEvent, - WebKitMediaKeySession, - WebKitMediaKeys, - DOMFileSystem, - FileSystemDirectoryEntry, - FileSystemDirectoryReader, - FileSystemEntry, - FileSystemFileEntry, - FetchHeaders, - FetchRequest, - FetchResponse, - FileSystemDirectoryHandle, - FileSystemFileHandle, - FileSystemHandle, - FileSystemSyncAccessHandle, - Gamepad, - GamepadButton, - GamepadEvent, - Geolocation, - GeolocationCoordinates, - GeolocationPosition, - GeolocationPositionError, - Highlight, - HighlightRegister, - IDBCursor, - IDBCursorWithValue, - IDBDatabase, - IDBFactory, - IDBIndex, - IDBKeyRange, - IDBObjectStore, - IDBOpenDBRequest, - IDBRequest, - IDBTransaction, - IDBVersionChangeEvent, - MediaCapabilities, - MediaControlsHost, - BlobEvent, - MediaRecorder, - MediaRecorderErrorEvent, - MediaMetadata, - MediaSession, - MediaSessionCoordinator, - MediaSource, - SourceBuffer, - SourceBufferList, - VideoPlaybackQuality, - CanvasCaptureMediaStreamTrack, - MediaDeviceInfo, - MediaDevices, - MediaStream, - MediaStreamTrack, - MediaStreamTrackEvent, - OverconstrainedError, - OverconstrainedErrorEvent, - RTCCertificate, - RTCDTMFSender, - RTCDTMFToneChangeEvent, - RTCDataChannel, - RTCDataChannelEvent, - RTCDtlsTransport, - RTCEncodedAudioFrame, - RTCEncodedVideoFrame, - RTCError, - RTCErrorEvent, - RTCIceCandidate, - RTCIceTransport, - RTCPeerConnection, - RTCPeerConnectionIceErrorEvent, - RTCPeerConnectionIceEvent, - RTCRtpReceiver, - RTCRtpSFrameTransform, - RTCRtpSFrameTransformErrorEvent, - RTCRtpScriptTransform, - RTCRtpScriptTransformer, - RTCRtpSender, - RTCRtpTransceiver, - RTCSctpTransport, - RTCSessionDescription, - RTCStatsReport, - RTCTrackEvent, - RTCTransformEvent, - HTMLModelElement, - Notification, - NotificationEvent, - MerchantValidationEvent, - PaymentAddress, - PaymentMethodChangeEvent, - PaymentRequest, - PaymentRequestUpdateEvent, - PaymentResponse, - PermissionStatus, - Permissions, - PictureInPictureEvent, - PictureInPictureWindow, - PushEvent, - PushManager, - PushMessageData, - PushSubscription, - PushSubscriptionChangeEvent, - PushSubscriptionOptions, - RemotePlayback, - SpeechRecognition, - SpeechRecognitionAlternative, - SpeechRecognitionErrorEvent, - SpeechRecognitionEvent, - SpeechRecognitionResult, - SpeechRecognitionResultList, - SpeechSynthesis, - SpeechSynthesisErrorEvent, - SpeechSynthesisEvent, - SpeechSynthesisUtterance, - SpeechSynthesisVoice, - StorageManager, - ByteLengthQueuingStrategy, - CountQueuingStrategy, - ReadableByteStreamController, - ReadableStream, - ReadableStreamBYOBReader, - ReadableStreamBYOBRequest, - ReadableStreamDefaultController, - ReadableStreamDefaultReader, - TransformStream, - TransformStreamDefaultController, - CompressionStream, - DecompressionStream, - WritableStream, - WritableStreamDefaultController, - WritableStreamDefaultWriter, - WebLock, - WebLockManager, - AnalyserNode, - AudioBuffer, - AudioBufferSourceNode, - AudioContext, - AudioDestinationNode, - AudioListener, - AudioNode, - AudioParam, - AudioParamMap, - AudioProcessingEvent, - AudioScheduledSourceNode, - AudioWorklet, - AudioWorkletGlobalScope, - AudioWorkletNode, - AudioWorkletProcessor, - BaseAudioContext, - BiquadFilterNode, - ChannelMergerNode, - ChannelSplitterNode, - ConstantSourceNode, - ConvolverNode, - DelayNode, - DynamicsCompressorNode, - GainNode, - IIRFilterNode, - MediaElementAudioSourceNode, - MediaStreamAudioDestinationNode, - MediaStreamAudioSourceNode, - OfflineAudioCompletionEvent, - OfflineAudioContext, - OscillatorNode, - PannerNode, - PeriodicWave, - ScriptProcessorNode, - StereoPannerNode, - WaveShaperNode, - AuthenticatorAssertionResponse, - AuthenticatorAttestationResponse, - AuthenticatorResponse, - PublicKeyCredential, - VideoColorSpace, - Database, - SQLError, - SQLResultSet, - SQLResultSetRowList, - SQLTransaction, - CloseEvent, - WebSocket, - WebXRBoundedReferenceSpace, - WebXRFrame, - WebXRHand, - WebXRInputSource, - WebXRInputSourceArray, - WebXRJointPose, - WebXRJointSpace, - WebXRLayer, - WebXRPose, - WebXRReferenceSpace, - WebXRRenderState, - WebXRRigidTransform, - WebXRSession, - WebXRSpace, - WebXRSystem, - WebXRView, - WebXRViewerPose, - WebXRViewport, - WebXRWebGLLayer, - XRInputSourceEvent, - XRInputSourcesChangeEvent, - XRReferenceSpaceEvent, - XRSessionEvent, - AnimationEffect, - AnimationPlaybackEvent, - AnimationTimeline, - CSSAnimation, - CSSTransition, - CustomEffect, - DocumentTimeline, - KeyframeEffect, - WebAnimation, - CryptoKey, - SubtleCrypto, - CSSConditionRule, - CSSContainerRule, - CSSCounterStyleRule, - CSSFontFaceRule, - CSSFontPaletteValuesRule, - CSSGroupingRule, - CSSImportRule, - CSSKeyframeRule, - CSSKeyframesRule, - CSSLayerBlockRule, - CSSLayerStatementRule, - CSSMediaRule, - CSSNamespaceRule, - CSSPageRule, - CSSPaintSize, - CSSRule, - CSSRuleList, - CSSStyleDeclaration, - CSSStyleRule, - CSSStyleSheet, - CSSSupportsRule, - CSSUnknownRule, - DOMCSSNamespace, - DOMMatrix, - DOMMatrixReadOnly, - DeprecatedCSSOMCounter, - DeprecatedCSSOMPrimitiveValue, - DeprecatedCSSOMRGBColor, - DeprecatedCSSOMRect, - DeprecatedCSSOMValue, - DeprecatedCSSOMValueList, - FontFace, - FontFaceSet, - MediaList, - MediaQueryList, - MediaQueryListEvent, - StyleMedia, - StyleSheet, - StyleSheetList, - CSSKeywordValue, - CSSNumericValue, - CSSOMVariableReferenceValue, - CSSStyleImageValue, - CSSStyleValue, - CSSUnitValue, - CSSUnparsedValue, - StylePropertyMap, - StylePropertyMapReadOnly, - CSSColor, - CSSColorValue, - CSSHSL, - CSSHWB, - CSSLCH, - CSSLab, - CSSOKLCH, - CSSOKLab, - CSSRGB, - CSSMathInvert, - CSSMathMax, - CSSMathMin, - CSSMathNegate, - CSSMathProduct, - CSSMathSum, - CSSMathValue, - CSSNumericArray, - CSSMatrixComponent, - CSSPerspective, - CSSRotate, - CSSScale, - CSSSkew, - CSSSkewX, - CSSSkewY, - CSSTransformComponent, - CSSTransformValue, - CSSTranslate, AbortController, AbortSignal, - AbstractRange, - AnimationEvent, - Attr, - BeforeUnloadEvent, BroadcastChannel, - CDATASection, - CharacterData, - ClipboardEvent, - Comment, - CompositionEvent, - CustomElementRegistry, + ByteLengthQueuingStrategy, + CloseEvent, + CompressionStream, + CountQueuingStrategy, + CryptoKey, CustomEvent, DOMException, - DOMImplementation, - DOMPoint, - DOMPointReadOnly, - DOMQuad, - DOMRect, - DOMRectList, - DOMRectReadOnly, - DOMStringList, - DOMStringMap, - DataTransfer, - DataTransferItem, - DataTransferItemList, - DeviceMotionEvent, - DeviceOrientationEvent, - Document, - DocumentFragment, - DocumentType, - DragEvent, - Element, + DOMFormData, + DOMURL, + DecompressionStream, ErrorEvent, Event, - EventListener, EventTarget, - FocusEvent, - FormDataEvent, - HashChangeEvent, - IdleDeadline, - InputEvent, - KeyboardEvent, + FetchHeaders, MessageChannel, MessageEvent, MessagePort, - MouseEvent, - MutationEvent, - MutationObserver, - MutationRecord, - NamedNodeMap, - Node, - NodeFilter, - NodeIterator, - NodeList, - OverflowEvent, - PageTransitionEvent, - PointerEvent, - PopStateEvent, - ProcessingInstruction, - ProgressEvent, - PromiseRejectionEvent, - Range, - SecurityPolicyViolationEvent, - ShadowRoot, - StaticRange, - Text, - TextDecoder, - TextDecoderStream, - TextDecoderStreamDecoder, - TextEncoder, - TextEncoderStream, - TextEncoderStreamEncoder, - TextEvent, - TransitionEvent, - TreeWalker, - UIEvent, - WheelEvent, - XMLDocument, - Blob, - File, - FileList, - FileReader, - FileReaderSync, - DOMFormData, - DOMTokenList, - DOMURL, - HTMLAllCollection, - HTMLAnchorElement, - HTMLAreaElement, - HTMLAttachmentElement, - HTMLAudioElement, - HTMLAudioElementLegacyFactory, - HTMLBRElement, - HTMLBaseElement, - HTMLBodyElement, - HTMLButtonElement, - HTMLCanvasElement, - HTMLCollection, - HTMLDListElement, - HTMLDataElement, - HTMLDataListElement, - HTMLDetailsElement, - HTMLDialogElement, - HTMLDirectoryElement, - HTMLDivElement, - HTMLDocument, - HTMLElement, - HTMLEmbedElement, - HTMLFieldSetElement, - HTMLFontElement, - HTMLFormControlsCollection, - HTMLFormElement, - HTMLFrameElement, - HTMLFrameSetElement, - HTMLHRElement, - HTMLHeadElement, - HTMLHeadingElement, - HTMLHtmlElement, - HTMLIFrameElement, - HTMLImageElement, - HTMLImageElementLegacyFactory, - HTMLInputElement, - HTMLLIElement, - HTMLLabelElement, - HTMLLegendElement, - HTMLLinkElement, - HTMLMapElement, - HTMLMarqueeElement, - HTMLMediaElement, - HTMLMenuElement, - HTMLMenuItemElement, - HTMLMetaElement, - HTMLMeterElement, - HTMLModElement, - HTMLOListElement, - HTMLObjectElement, - HTMLOptGroupElement, - HTMLOptionElement, - HTMLOptionElementLegacyFactory, - HTMLOptionsCollection, - HTMLOutputElement, - HTMLParagraphElement, - HTMLParamElement, - HTMLPictureElement, - HTMLPreElement, - HTMLProgressElement, - HTMLQuoteElement, - HTMLScriptElement, - HTMLSelectElement, - HTMLSlotElement, - HTMLSourceElement, - HTMLSpanElement, - HTMLStyleElement, - HTMLTableCaptionElement, - HTMLTableCellElement, - HTMLTableColElement, - HTMLTableElement, - HTMLTableRowElement, - HTMLTableSectionElement, - HTMLTemplateElement, - HTMLTextAreaElement, - HTMLTimeElement, - HTMLTitleElement, - HTMLTrackElement, - HTMLUListElement, - HTMLUnknownElement, - HTMLVideoElement, - ImageBitmap, - ImageData, - MediaController, - MediaEncryptedEvent, - MediaError, - OffscreenCanvas, - RadioNodeList, - SubmitEvent, - TextMetrics, - TimeRanges, - URLSearchParams, - ValidityState, - WebKitMediaKeyError, - ANGLEInstancedArrays, - CanvasGradient, - CanvasPattern, - CanvasRenderingContext2D, - EXTBlendMinMax, - EXTColorBufferFloat, - EXTColorBufferHalfFloat, - EXTFloatBlend, - EXTFragDepth, - EXTShaderTextureLOD, - EXTTextureCompressionRGTC, - EXTTextureFilterAnisotropic, - EXTsRGB, - ImageBitmapRenderingContext, - KHRParallelShaderCompile, - OESElementIndexUint, - OESFBORenderMipmap, - OESStandardDerivatives, - OESTextureFloat, - OESTextureFloatLinear, - OESTextureHalfFloat, - OESTextureHalfFloatLinear, - OESVertexArrayObject, - OffscreenCanvasRenderingContext2D, - PaintRenderingContext2D, - Path2D, - WebGL2RenderingContext, - WebGLActiveInfo, - WebGLBuffer, - WebGLColorBufferFloat, - WebGLCompressedTextureASTC, - WebGLCompressedTextureATC, - WebGLCompressedTextureETC, - WebGLCompressedTextureETC1, - WebGLCompressedTexturePVRTC, - WebGLCompressedTextureS3TC, - WebGLCompressedTextureS3TCsRGB, - WebGLContextEvent, - WebGLDebugRendererInfo, - WebGLDebugShaders, - WebGLDepthTexture, - WebGLDrawBuffers, - WebGLFramebuffer, - WebGLLoseContext, - WebGLMultiDraw, - WebGLProgram, - WebGLQuery, - WebGLRenderbuffer, - WebGLRenderingContext, - WebGLSampler, - WebGLShader, - WebGLShaderPrecisionFormat, - WebGLSync, - WebGLTexture, - WebGLTransformFeedback, - WebGLUniformLocation, - WebGLVertexArrayObject, - WebGLVertexArrayObjectOES, - AudioTrack, - AudioTrackConfiguration, - AudioTrackList, - DataCue, - TextTrack, - TextTrackCue, - TextTrackCueGeneric, - TextTrackCueList, - TextTrackList, - TrackEvent, - VTTCue, - VTTRegion, - VTTRegionList, - VideoTrack, - VideoTrackConfiguration, - VideoTrackList, - CommandLineAPIHost, - InspectorAuditAccessibilityObject, - InspectorAuditDOMObject, - InspectorAuditResourcesObject, - InspectorFrontendHost, - DOMApplicationCache, - MathMLElement, - MathMLMathElement, - BarProp, - Crypto, - DOMSelection, - DOMWindow, - EventSource, - History, - IntersectionObserver, - IntersectionObserverEntry, - Location, - Navigator, Performance, PerformanceEntry, PerformanceMark, PerformanceMeasure, - PerformanceNavigation, - PerformanceNavigationTiming, PerformanceObserver, PerformanceObserverEntryList, - PerformancePaintTiming, PerformanceResourceTiming, PerformanceServerTiming, PerformanceTiming, - RemoteDOMWindow, - ResizeObserver, - ResizeObserverEntry, - ResizeObserverSize, - Screen, - ShadowRealmGlobalScope, - UndoItem, - UndoManager, - UserMessageHandler, - UserMessageHandlersNamespace, - VisualViewport, - WebKitNamespace, - WebKitPoint, - WorkerNavigator, - DOMMimeType, - DOMMimeTypeArray, - DOMPlugin, - DOMPluginArray, - Storage, - StorageEvent, - SVGAElement, - SVGAltGlyphDefElement, - SVGAltGlyphElement, - SVGAltGlyphItemElement, - SVGAngle, - SVGAnimateColorElement, - SVGAnimateElement, - SVGAnimateMotionElement, - SVGAnimateTransformElement, - SVGAnimatedAngle, - SVGAnimatedBoolean, - SVGAnimatedEnumeration, - SVGAnimatedInteger, - SVGAnimatedLength, - SVGAnimatedLengthList, - SVGAnimatedNumber, - SVGAnimatedNumberList, - SVGAnimatedPreserveAspectRatio, - SVGAnimatedRect, - SVGAnimatedString, - SVGAnimatedTransformList, - SVGAnimationElement, - SVGCircleElement, - SVGClipPathElement, - SVGComponentTransferFunctionElement, - SVGCursorElement, - SVGDefsElement, - SVGDescElement, - SVGElement, - SVGEllipseElement, - SVGFEBlendElement, - SVGFEColorMatrixElement, - SVGFEComponentTransferElement, - SVGFECompositeElement, - SVGFEConvolveMatrixElement, - SVGFEDiffuseLightingElement, - SVGFEDisplacementMapElement, - SVGFEDistantLightElement, - SVGFEDropShadowElement, - SVGFEFloodElement, - SVGFEFuncAElement, - SVGFEFuncBElement, - SVGFEFuncGElement, - SVGFEFuncRElement, - SVGFEGaussianBlurElement, - SVGFEImageElement, - SVGFEMergeElement, - SVGFEMergeNodeElement, - SVGFEMorphologyElement, - SVGFEOffsetElement, - SVGFEPointLightElement, - SVGFESpecularLightingElement, - SVGFESpotLightElement, - SVGFETileElement, - SVGFETurbulenceElement, - SVGFilterElement, - SVGFontElement, - SVGFontFaceElement, - SVGFontFaceFormatElement, - SVGFontFaceNameElement, - SVGFontFaceSrcElement, - SVGFontFaceUriElement, - SVGForeignObjectElement, - SVGGElement, - SVGGeometryElement, - SVGGlyphElement, - SVGGlyphRefElement, - SVGGradientElement, - SVGGraphicsElement, - SVGHKernElement, - SVGImageElement, - SVGLength, - SVGLengthList, - SVGLineElement, - SVGLinearGradientElement, - SVGMPathElement, - SVGMarkerElement, - SVGMaskElement, - SVGMatrix, - SVGMetadataElement, - SVGMissingGlyphElement, - SVGNumber, - SVGNumberList, - SVGPathElement, - SVGPathSeg, - SVGPathSegArcAbs, - SVGPathSegArcRel, - SVGPathSegClosePath, - SVGPathSegCurvetoCubicAbs, - SVGPathSegCurvetoCubicRel, - SVGPathSegCurvetoCubicSmoothAbs, - SVGPathSegCurvetoCubicSmoothRel, - SVGPathSegCurvetoQuadraticAbs, - SVGPathSegCurvetoQuadraticRel, - SVGPathSegCurvetoQuadraticSmoothAbs, - SVGPathSegCurvetoQuadraticSmoothRel, - SVGPathSegLinetoAbs, - SVGPathSegLinetoHorizontalAbs, - SVGPathSegLinetoHorizontalRel, - SVGPathSegLinetoRel, - SVGPathSegLinetoVerticalAbs, - SVGPathSegLinetoVerticalRel, - SVGPathSegList, - SVGPathSegMovetoAbs, - SVGPathSegMovetoRel, - SVGPatternElement, - SVGPoint, - SVGPointList, - SVGPolygonElement, - SVGPolylineElement, - SVGPreserveAspectRatio, - SVGRadialGradientElement, - SVGRect, - SVGRectElement, - SVGRenderingIntent, - SVGSVGElement, - SVGScriptElement, - SVGSetElement, - SVGStopElement, - SVGStringList, - SVGStyleElement, - SVGSwitchElement, - SVGSymbolElement, - SVGTRefElement, - SVGTSpanElement, - SVGTextContentElement, - SVGTextElement, - SVGTextPathElement, - SVGTextPositioningElement, - SVGTitleElement, - SVGTransform, - SVGTransformList, - SVGUnitTypes, - SVGUseElement, - SVGVKernElement, - SVGViewElement, - SVGViewSpec, - SVGZoomEvent, - GCObservation, - InternalSettings, - Internals, - InternalsMapLike, - InternalsSetLike, - MallocStatistics, - MemoryInfo, - MockCDMFactory, - MockContentFilterSettings, - MockPageOverlay, - MockPaymentCoordinator, - ServiceWorkerInternals, - TypeConversions, - WebFakeXRDevice, - WebFakeXRInputController, - WebXRTest, - DedicatedWorkerGlobalScope, + ReadableByteStreamController, + ReadableStream, + ReadableStreamBYOBReader, + ReadableStreamBYOBRequest, + ReadableStreamDefaultController, + ReadableStreamDefaultReader, + SubtleCrypto, + TextDecoderStream, + TextEncoder, + TextEncoderStream, + TransformStream, + TransformStreamDefaultController, + URLSearchParams, + WebSocket, Worker, - WorkerGlobalScope, - WorkerLocation, - ExtendableEvent, - ExtendableMessageEvent, - FetchEvent, - NavigationPreloadManager, - ServiceWorker, - ServiceWorkerClient, - ServiceWorkerClients, - ServiceWorkerContainer, - ServiceWorkerGlobalScope, - ServiceWorkerRegistration, - ServiceWorkerWindowClient, - SharedWorker, - SharedWorkerGlobalScope, - PaintWorkletGlobalScope, - Worklet, - WorkletGlobalScope, - CustomXPathNSResolver, - DOMParser, - XMLHttpRequest, - XMLHttpRequestEventTarget, - XMLHttpRequestProgressEvent, - XMLHttpRequestUpload, - XMLSerializer, - XPathEvaluator, - XPathExpression, - XPathNSResolver, - XPathResult, - XSLTProcessor, + WritableStream, + WritableStreamDefaultController, + WritableStreamDefaultWriter, // --bun-- Cookie, CookieMap, EventEmitter, URLPattern, -}; - -static constexpr unsigned numberOfDOMConstructorsBase = 845; -static constexpr unsigned bunExtraConstructors = 4; + // Keep last. Sizes ConstructorArray. + Count, +}; -static constexpr unsigned numberOfDOMConstructors = numberOfDOMConstructorsBase + bunExtraConstructors; +static constexpr unsigned numberOfDOMConstructors = static_cast(DOMConstructorID::Count); class DOMConstructors { WTF_MAKE_NONCOPYABLE(DOMConstructors); diff --git a/src/jsc/bindings/webcore/JSPerformance.h b/src/jsc/bindings/webcore/JSPerformance.h index 0cbb94095963..98ea1a6803b6 100644 --- a/src/jsc/bindings/webcore/JSPerformance.h +++ b/src/jsc/bindings/webcore/JSPerformance.h @@ -27,8 +27,6 @@ namespace WebCore { -class JSPerformanceObject; - class JSPerformance : public JSEventTarget { public: using Base = JSEventTarget; diff --git a/src/jsc/bindings/webcore/SerializedScriptValue.h b/src/jsc/bindings/webcore/SerializedScriptValue.h index 78347c7980c3..76117fd1fa2b 100644 --- a/src/jsc/bindings/webcore/SerializedScriptValue.h +++ b/src/jsc/bindings/webcore/SerializedScriptValue.h @@ -43,7 +43,6 @@ namespace JSC { namespace Wasm { class Module; -class MemoryHandle; } } #endif @@ -81,7 +80,6 @@ enum class FastPath : uint8_t { class MessagePort; class CloneSerializer; -class FragmentedSharedBuffer; enum class SerializationReturnCode; enum class SerializationErrorMode { NonThrowing, diff --git a/src/runtime/api/crash_handler_jsc.rs b/src/runtime/api/crash_handler_jsc.rs index d573f171b4af..79a6f931c22f 100644 --- a/src/runtime/api/crash_handler_jsc.rs +++ b/src/runtime/api/crash_handler_jsc.rs @@ -129,7 +129,7 @@ pub(crate) mod js_bindings { #[bun_jsc::host_fn] fn js_panic(_global: &JSGlobalObject, _frame: &CallFrame) -> JsResult { crash_handler::suppress_core_dumps_if_necessary(); - crash_handler::panic_impl(b"invoked crashByPanic() handler", None, None); + crash_handler::panic_impl(b"invoked crashByPanic() handler", None); } #[bun_jsc::host_fn] @@ -199,7 +199,7 @@ pub(crate) mod js_bindings { #[bun_jsc::host_fn] fn js_root_error(_global: &JSGlobalObject, _frame: &CallFrame) -> JsResult { - crash_handler::handle_root_error("Unexpected", None); + crash_handler::handle_root_error("Unexpected"); } #[bun_jsc::host_fn] diff --git a/src/runtime/cli/Arguments.rs b/src/runtime/cli/Arguments.rs index 0ace6e3b893f..1724d455ade1 100644 --- a/src/runtime/cli/Arguments.rs +++ b/src/runtime/cli/Arguments.rs @@ -74,21 +74,6 @@ macro_rules! maybe_debug_params { }; } -// `bun_crash_handler::VERBOSE_ERROR_TRACE` gates extra crash diagnostics. -// Expose the flag in crash-trace builds (debug/test/asan). -const VERBOSE_ERROR_TRACE_PARAMS: &[ParamType] = &[parse_param!( - "--verbose-error-trace Dump error return traces" -)]; -macro_rules! maybe_verbose_error_trace { - () => { - if bun_core::env::SHOW_CRASH_TRACE { - VERBOSE_ERROR_TRACE_PARAMS - } else { - &[] as &[ParamType] - } - }; -} - const BASE_PARAMS_: &[ParamType] = concat_params!( maybe_debug_params!(), &[ @@ -104,7 +89,6 @@ const BASE_PARAMS_: &[ParamType] = concat_params!( ), parse_param!("-h, --help Display this menu and exit"), ], - maybe_verbose_error_trace!(), &[parse_param!("...")], ); @@ -819,11 +803,6 @@ pub(crate) fn parse(cmd: CommandTag, ctx: Context<'_>) -> crate::Result>`, // so we dupe into a plain `Box<[u8]>`. diff --git a/src/runtime/cli/mod.rs b/src/runtime/cli/mod.rs index 292db89d5bfd..6478ac574494 100644 --- a/src/runtime/cli/mod.rs +++ b/src/runtime/cli/mod.rs @@ -584,7 +584,7 @@ pub mod cli { let _ = log.print(std::ptr::from_mut::( bun_core::Output::error_writer(), )); - bun_crash_handler::handle_root_error(err, None); + bun_crash_handler::handle_root_error(err); } } } diff --git a/src/uws_sys/Loop.rs b/src/uws_sys/Loop.rs index 9d5e8c38e777..d7800ec68f92 100644 --- a/src/uws_sys/Loop.rs +++ b/src/uws_sys/Loop.rs @@ -307,40 +307,6 @@ impl PosixLoop { unsafe { c::uws_loop_defer(self, user_data, defer_callback) }; } - // Same trampoline-synthesis limitation as `next_tick` — callers pass the - // C-ABI callback directly. The returned `Handler` stores it for later removal. - // - // Takes `this: *mut Self` (not `&mut self`) so the stored `Handler.loop_` inherits the - // long-lived raw-pointer provenance from `us_create_loop`/`uws_get_loop`. Routing through - // a `&mut self` reborrow would bound the stored pointer's provenance to this call, and any - // subsequent `&mut`/`&` to the C-owned singleton would invalidate it under Stacked Borrows, - // making the later FFI write in `Handler::remove_*` UB. - /// # Safety - /// `this` must be the live C-allocated loop pointer returned by - /// `us_create_loop`/`uws_get_loop` (not derived from a `&mut` reborrow). - pub unsafe fn add_post_handler( - this: *mut Self, - ctx: *mut c_void, - callback: unsafe extern "C" fn(*mut c_void, *mut Loop), - ) -> Handler { - // SAFETY: `this` is the live C-allocated loop pointer per fn contract. - unsafe { c::uws_loop_addPostHandler(this, ctx, callback) }; - Handler { loop_: this } - } - - /// # Safety - /// `this` must be the live C-allocated loop pointer returned by - /// `us_create_loop`/`uws_get_loop` (not derived from a `&mut` reborrow). - pub unsafe fn add_pre_handler( - this: *mut Self, - ctx: *mut c_void, - callback: unsafe extern "C" fn(*mut c_void, *mut Loop), - ) -> Handler { - // SAFETY: `this` is the live C-allocated loop pointer per fn contract. - unsafe { c::uws_loop_addPreHandler(this, ctx, callback) }; - Handler { loop_: this } - } - pub fn run(&mut self) { // SAFETY: self is a valid loop pointer unsafe { c::us_loop_run(self) }; @@ -363,15 +329,6 @@ impl PosixLoop { } } -/// Stores the loop ref and the C-ABI callback so it can be unregistered later. -/// -/// Stores `*mut Loop` (not `&Loop`) -/// — the loop is C-owned/heap-allocated and the FFI remove calls mutate it, so a -/// shared `&Loop` would make the `*const → *mut` cast UB when written through. -pub struct Handler { - pub loop_: *mut Loop, -} - // ───────────────────────────── WindowsLoop ───────────────────────────── #[cfg(windows)] @@ -553,37 +510,6 @@ impl WindowsLoop { // SAFETY: `this` was returned by us_create_loop/uws_get_loop_with_native and not yet freed unsafe { c::us_loop_free(this) }; } - - // See PosixLoop::add_post_handler — same trampoline-synthesis limitation. - // Takes `this: *mut Self` (not `&mut self`) so the stored `Handler.loop_` inherits the - // long-lived raw-pointer provenance from `us_create_loop`/`uws_get_loop_with_native` - // rather than a transient `&mut` reborrow (which Stacked Borrows would invalidate on the - // next access to the C-owned singleton). - /// # Safety - /// `this` must be the live C-allocated loop pointer returned by - /// `us_create_loop`/`uws_get_loop_with_native` (not derived from a `&mut` reborrow). - pub unsafe fn add_post_handler( - this: *mut Self, - ctx: *mut c_void, - callback: unsafe extern "C" fn(*mut c_void, *mut Loop), - ) -> Handler { - // SAFETY: `this` is the live C-allocated loop pointer per fn contract. - unsafe { c::uws_loop_addPostHandler(this, ctx, callback) }; - Handler { loop_: this } - } - - /// # Safety - /// `this` must be the live C-allocated loop pointer returned by - /// `us_create_loop`/`uws_get_loop_with_native` (not derived from a `&mut` reborrow). - pub unsafe fn add_pre_handler( - this: *mut Self, - ctx: *mut c_void, - callback: unsafe extern "C" fn(*mut c_void, *mut Loop), - ) -> Handler { - // SAFETY: `this` is the live C-allocated loop pointer per fn contract. - unsafe { c::uws_loop_addPreHandler(this, ctx, callback) }; - Handler { loop_: this } - } } // ───────────────────────────── Loop alias ───────────────────────────── @@ -596,7 +522,6 @@ pub type Loop = PosixLoop; // ───────────────────────────── extern "C" ───────────────────────────── type LoopCb = unsafe extern "C" fn(*mut Loop); -type LoopCtxCb = unsafe extern "C" fn(ctx: *mut c_void, loop_: *mut Loop); type DeferCb = unsafe extern "C" fn(ctx: *mut c_void); #[allow(non_snake_case)] @@ -624,8 +549,6 @@ mod c { #[cfg(windows)] pub(super) fn us_loop_pump(loop_: *mut Loop); pub fn us_wakeup_loop(loop_: *mut Loop); - pub(super) fn uws_loop_addPostHandler(loop_: *mut Loop, ctx: *mut c_void, cb: LoopCtxCb); - pub(super) fn uws_loop_addPreHandler(loop_: *mut Loop, ctx: *mut c_void, cb: LoopCtxCb); #[cfg(not(windows))] pub(super) fn us_loop_run_bun_tick( loop_: *mut Loop, diff --git a/src/uws_sys/Response.rs b/src/uws_sys/Response.rs index d0650880c162..ebd439bc8663 100644 --- a/src/uws_sys/Response.rs +++ b/src/uws_sys/Response.rs @@ -302,18 +302,6 @@ impl Response { } } - pub fn override_write_offset(&mut self, offset: T) - where - u64: TryFrom, - >::Error: core::fmt::Debug, - { - c::uws_res_override_write_offset( - Self::ssl_flag(), - self.as_raw(), - u64::try_from(offset).expect("int cast"), - ) - } - pub(crate) fn has_responded(&mut self) -> bool { c::uws_res_has_responded(Self::ssl_flag(), self.as_raw()) } @@ -1172,7 +1160,6 @@ pub mod c { data: *const u8, length: usize, ); - pub(crate) safe fn uws_res_override_write_offset(ssl: i32, res: &mut uws_res, offset: u64); pub(crate) safe fn uws_res_has_responded(ssl: i32, res: &mut uws_res) -> bool; // safe: `&mut uws_res` is ABI-identical to a non-null `*mut uws_res`; // `handler`/`user_data` are stored opaquely (never dereferenced by the diff --git a/src/uws_sys/WebSocket.rs b/src/uws_sys/WebSocket.rs index 66c069458834..1dc60d2ebe85 100644 --- a/src/uws_sys/WebSocket.rs +++ b/src/uws_sys/WebSocket.rs @@ -539,28 +539,6 @@ pub mod c { compress: bool, fin: bool, ) -> SendStatus; - pub fn uws_ws_send_fragment( - ssl: i32, - ws: *mut RawWebSocket, - message: *const u8, - length: usize, - compress: bool, - ) -> SendStatus; - pub fn uws_ws_send_first_fragment( - ssl: i32, - ws: *mut RawWebSocket, - message: *const u8, - length: usize, - compress: bool, - ) -> SendStatus; - pub fn uws_ws_send_first_fragment_with_opcode( - ssl: i32, - ws: *mut RawWebSocket, - message: *const u8, - length: usize, - opcode: Opcode, - compress: bool, - ) -> SendStatus; pub(crate) fn uws_ws_end( ssl: i32, ws: *mut RawWebSocket, @@ -622,10 +600,5 @@ pub mod c { ws: &mut RawWebSocket, dest: &mut *mut u8, ) -> usize; - pub safe fn uws_ws_get_remote_address_as_text( - ssl: i32, - ws: &mut RawWebSocket, - dest: &mut *mut u8, - ) -> usize; } } diff --git a/src/uws_sys/_libusockets.h b/src/uws_sys/_libusockets.h index 8f49e123ca36..395398448b62 100644 --- a/src/uws_sys/_libusockets.h +++ b/src/uws_sys/_libusockets.h @@ -132,13 +132,6 @@ typedef void (*uws_listen_domain_handler)( typedef void (*uws_method_handler)(uws_res_t* response, uws_req_t* request, void* user_data); typedef void (*uws_filter_handler)(uws_res_t* response, int, void* user_data); -typedef void (*uws_missing_server_handler)(const char* hostname, - void* user_data); -typedef void (*uws_get_headers_server_handler)(const char* header_name, - size_t header_name_size, - const char* header_value, - size_t header_value_size, - void* user_data); struct us_loop_t* uws_get_loop(); diff --git a/src/uws_sys/h3.rs b/src/uws_sys/h3.rs index da8962fa9ffa..6570be6260fc 100644 --- a/src/uws_sys/h3.rs +++ b/src/uws_sys/h3.rs @@ -169,9 +169,6 @@ impl Response { pub(crate) fn reset_timeout(&mut self) { c::uws_h3_res_reset_timeout(self) } - pub fn override_write_offset(&mut self, off: u64) { - c::uws_h3_res_override_write_offset(self, off) - } pub(crate) fn get_buffered_amount(&mut self) -> u64 { c::uws_h3_res_get_buffered_amount(self) } @@ -682,7 +679,6 @@ mod c { pub(super) safe fn uws_h3_res_write_mark(res: &mut Response); pub(super) safe fn uws_h3_res_flush_headers(res: &mut Response, immediate: bool); pub(super) fn uws_h3_res_write(res: *mut Response, p: *const u8, len: *mut usize) -> bool; - pub(super) safe fn uws_h3_res_override_write_offset(res: &mut Response, off: u64); pub(super) safe fn uws_h3_res_has_responded(res: &mut Response) -> bool; pub(super) safe fn uws_h3_res_get_buffered_amount(res: &mut Response) -> u64; pub(super) safe fn uws_h3_res_reset_timeout(res: &mut Response); diff --git a/src/uws_sys/lib.rs b/src/uws_sys/lib.rs index b0da133ea77c..fe32cf519dde 100644 --- a/src/uws_sys/lib.rs +++ b/src/uws_sys/lib.rs @@ -29,7 +29,6 @@ pub const LIBUS_SOCKET_ALLOW_HALF_OPEN: core::ffi::c_int = 2; pub const LIBUS_LISTEN_REUSE_PORT: core::ffi::c_int = 4; pub const LIBUS_SOCKET_IPV6_ONLY: core::ffi::c_int = 8; pub const LIBUS_LISTEN_REUSE_ADDR: core::ffi::c_int = 16; -pub const LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE: core::ffi::c_int = 32; /// BoringSSL `SSL_CTX` (alias so callers don't need a direct boringssl dep). pub type SslCtx = bun_boringssl_sys::SSL_CTX; @@ -436,7 +435,6 @@ pub mod fault_inject { unsafe extern "C" { pub fn us_fault_set(syscall: c_int, rule: *const UsFaultRule); - pub safe fn us_fault_clear(syscall: c_int); pub safe fn us_fault_clear_all(); pub fn us_fault_hit(syscall: c_int, fd: c_int, out: *mut isize, clamp: *mut c_int) -> c_int; diff --git a/src/uws_sys/libuwsockets.cpp b/src/uws_sys/libuwsockets.cpp index 1effe11c0026..a6b1438067e0 100644 --- a/src/uws_sys/libuwsockets.cpp +++ b/src/uws_sys/libuwsockets.cpp @@ -479,25 +479,6 @@ extern "C" } } - /* callback, path to unix domain socket */ - void uws_app_listen_domain(int ssl, uws_app_t *app, const char *domain, size_t pathlen, uws_listen_domain_handler handler, void *user_data) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - uwsApp->listen(0,[handler, domain, user_data](struct us_listen_socket_t *listen_socket) - { handler((struct us_listen_socket_t *)listen_socket, domain, 0, user_data); }, - {domain, pathlen}); - } - else - { - uWS::App *uwsApp = (uWS::App *)app; - uwsApp->listen(0, [handler, domain, user_data](struct us_listen_socket_t *listen_socket) - { handler((struct us_listen_socket_t *)listen_socket, domain, 0, user_data); }, - {domain, pathlen}); - } - } - /* callback, path to unix domain socket */ void uws_app_listen_domain_with_options(int ssl, uws_app_t *app, const char *domain, size_t pathlen, int options, uws_listen_domain_handler handler, void *user_data) { @@ -566,21 +547,6 @@ extern "C" } } - bool uws_constructor_failed(int ssl, uws_app_t *app) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - if (!uwsApp) - return true; - return uwsApp->constructorFailed(); - } - uWS::App *uwsApp = (uWS::App *)app; - if (!uwsApp) - return true; - return uwsApp->constructorFailed(); - } - unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic, size_t topic_length) { if (ssl) @@ -607,44 +573,6 @@ extern "C" stringViewFromC(message, message_length), (uWS::OpCode)(unsigned char)opcode, compress); } - void *uws_get_native_handle(int ssl, uws_app_t *app) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - return uwsApp->getNativeHandle(); - } - uWS::App *uwsApp = (uWS::App *)app; - return uwsApp->getNativeHandle(); - } - void uws_remove_server_name(int ssl, uws_app_t *app, - const char *hostname_pattern) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - uwsApp->removeServerName(hostname_pattern); - } - else - { - uWS::App *uwsApp = (uWS::App *)app; - uwsApp->removeServerName(hostname_pattern); - } - } - void uws_add_server_name(int ssl, uws_app_t *app, - const char *hostname_pattern) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - uwsApp->addServerName(hostname_pattern); - } - else - { - uWS::App *uwsApp = (uWS::App *)app; - uwsApp->addServerName(hostname_pattern); - } - } int uws_add_server_name_with_options( int ssl, uws_app_t *app, const char *hostname_pattern, struct us_bun_socket_context_options_t options, @@ -667,25 +595,6 @@ extern "C" return !success; } - void uws_missing_server_name(int ssl, uws_app_t *app, - uws_missing_server_handler handler, - void *user_data) - { - if (ssl) - { - uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; - uwsApp->missingServerName( - [handler, user_data](auto hostname) - { handler(hostname, user_data); }); - } - else - { - uWS::App *uwsApp = (uWS::App *)app; - uwsApp->missingServerName( - [handler, user_data](auto hostname) - { handler(hostname, user_data); }); - } - } void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, void *user_data) { @@ -856,22 +765,6 @@ extern "C" } } - uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message, - size_t length, uws_opcode_t opcode) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - return (uws_sendstatus_t)uws->send(stringViewFromC(message, length), - (uWS::OpCode)(unsigned char)opcode); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - return (uws_sendstatus_t)uws->send(stringViewFromC(message, length), - (uWS::OpCode)(unsigned char)opcode); - } - uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws, const char *message, size_t length, uws_opcode_t opcode, bool compress, @@ -896,74 +789,6 @@ extern "C" } } - uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws, - const char *message, size_t length, - bool compress) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - return (uws_sendstatus_t)uws->sendFragment( - stringViewFromC(message, length), compress); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - return (uws_sendstatus_t)uws->sendFragment(stringViewFromC(message, length), - compress); - } - uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws, - const char *message, size_t length, - bool compress) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - return (uws_sendstatus_t)uws->sendFirstFragment( - stringViewFromC(message, length), uWS::OpCode::BINARY, compress); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - return (uws_sendstatus_t)uws->sendFirstFragment( - stringViewFromC(message, length), uWS::OpCode::BINARY, compress); - } - uws_sendstatus_t - uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws, - const char *message, size_t length, - uws_opcode_t opcode, bool compress) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - return (uws_sendstatus_t)uws->sendFirstFragment( - stringViewFromC(message, length), (uWS::OpCode)(unsigned char)opcode, - compress); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - return (uws_sendstatus_t)uws->sendFirstFragment( - stringViewFromC(message, length), (uWS::OpCode)(unsigned char)opcode, - compress); - } - uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws, - const char *message, size_t length, - bool compress) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - return (uws_sendstatus_t)uws->sendLastFragment( - stringViewFromC(message, length), compress); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - return (uws_sendstatus_t)uws->sendLastFragment( - stringViewFromC(message, length), compress); - } - void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message, size_t length) { @@ -1062,23 +887,6 @@ extern "C" } } - uws_sendstatus_t uws_ws_publish(int ssl, uws_websocket_t *ws, const char *topic, - size_t topic_length, const char *message, - size_t message_length) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - return (uws_sendstatus_t)uws->publish(stringViewFromC(topic, topic_length), - stringViewFromC(message, message_length)); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - return (uws_sendstatus_t)uws->publish(stringViewFromC(topic, topic_length), - stringViewFromC(message, message_length)); - } - uws_sendstatus_t uws_ws_publish_with_options(int ssl, uws_websocket_t *ws, const char *topic, size_t topic_length, const char *message, size_t message_length, @@ -1131,26 +939,6 @@ extern "C" return value.length(); } - size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws, - const char **dest) - { - if (ssl) - { - TLSWebSocket *uws = - (TLSWebSocket *)ws; - - std::string_view value = uws->getRemoteAddressAsText(); - *dest = value.data(); - return value.length(); - } - TCPWebSocket *uws = - (TCPWebSocket *)ws; - - std::string_view value = uws->getRemoteAddressAsText(); - *dest = value.data(); - return value.length(); - } - void uws_res_end(int ssl, uws_res_r res, const char *data, size_t length, bool close_connection) { @@ -1503,18 +1291,6 @@ extern "C" } } - uint64_t uws_res_get_write_offset(int ssl, uws_res_r res) nonnull_fn_decl; - uint64_t uws_res_get_write_offset(int ssl, uws_res_r res) - { - if (ssl) - { - uWS::HttpResponse *uwsRes = (uWS::HttpResponse *)res; - return uwsRes->getWriteOffset(); - } - uWS::HttpResponse *uwsRes = (uWS::HttpResponse *)res; - return uwsRes->getWriteOffset(); - } - bool uws_res_has_responded(int ssl, uws_res_r res) nonnull_fn_decl; bool uws_res_has_responded(int ssl, uws_res_r res) { @@ -1670,18 +1446,6 @@ extern "C" } } - bool uws_req_is_ancient(uws_req_t *res) - { - uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; - return uwsReq->isAncient(); - } - - bool uws_req_get_yield(uws_req_t *res) - { - uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; - return uwsReq->getYield(); - } - void uws_req_set_yield(uws_req_t *res, bool yield) { uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; @@ -1718,25 +1482,6 @@ size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header, return value.length(); } - void uws_req_for_each_header(uws_req_t *res, uws_get_headers_server_handler handler, void *user_data) - { - uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; - for (auto header : *uwsReq) - { - handler(header.first.data(), header.first.length(), header.second.data(), header.second.length(), user_data); - } - } - - size_t uws_req_get_query(uws_req_t *res, const char *key, size_t key_length, - const char **dest) - { - uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; - - std::string_view value = uwsReq->getQuery(stringViewFromC(key, key_length)); - *dest = value.data(); - return value.length(); - } - size_t uws_req_get_parameter(uws_req_t *res, unsigned short index, const char **dest) { @@ -1787,30 +1532,6 @@ size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header, return (struct us_loop_t *)uWS::Loop::get(existing_native_loop); } - void uws_loop_addPostHandler(us_loop_t *loop, void *ctx_, - void (*cb)(void *ctx, us_loop_t *loop)) - { - uWS::Loop *uwsLoop = (uWS::Loop *)loop; - uwsLoop->addPostHandler(ctx_, [ctx_, cb](uWS::Loop *uwsLoop_) - { cb(ctx_, (us_loop_t *)uwsLoop_); }); - } - void uws_loop_removePostHandler(us_loop_t *loop, void *key) - { - uWS::Loop *uwsLoop = (uWS::Loop *)loop; - uwsLoop->removePostHandler(key); - } - void uws_loop_addPreHandler(us_loop_t *loop, void *ctx_, - void (*cb)(void *ctx, us_loop_t *loop)) - { - uWS::Loop *uwsLoop = (uWS::Loop *)loop; - uwsLoop->addPreHandler(ctx_, [ctx_, cb](uWS::Loop *uwsLoop_) - { cb(ctx_, (us_loop_t *)uwsLoop_); }); - } - void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_) - { - uWS::Loop *uwsLoop = (uWS::Loop *)loop; - uwsLoop->removePreHandler(ctx_); - } void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx)) { uWS::Loop *uwsLoop = (uWS::Loop *)loop; @@ -1844,18 +1565,6 @@ size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header, LIBUS_SOCKET_WRITABLE | ((s->flags.is_paused || s->read_eof) ? 0 : LIBUS_SOCKET_READABLE)); } - void uws_res_override_write_offset(int ssl, uws_res_r res, uint64_t offset) - { - if (ssl) - { - uWS::HttpResponse *uwsRes = (uWS::HttpResponse *)res; - uwsRes->setWriteOffset(offset); //TODO: when updated to master this will bechanged to overrideWriteOffset - } else { - uWS::HttpResponse *uwsRes = (uWS::HttpResponse *)res; - uwsRes->setWriteOffset(offset); //TODO: when updated to master this will bechanged to overrideWriteOffset - } - } - __attribute__((callback (corker, ctx))) void uws_res_cork(int ssl, uws_res_r res, void *ctx, void (*corker)(void *ctx)) nonnull_fn_decl; @@ -1967,16 +1676,6 @@ __attribute__((callback (corker, ctx))) } } - void *uws_res_get_socket_data(int ssl, uws_res_r res) { - if (ssl) { - uWS::HttpResponse *uwsRes = (uWS::HttpResponse *)res; - return uwsRes->getSocketData(); - } else { - uWS::HttpResponse *uwsRes = (uWS::HttpResponse *)res; - return uwsRes->getSocketData(); - } - } - bool uws_res_is_connect_request(int ssl, uws_res_r res) { if (ssl) { diff --git a/src/uws_sys/libuwsockets_h3.cpp b/src/uws_sys/libuwsockets_h3.cpp index b20cfba87859..ff98c721c776 100644 --- a/src/uws_sys/libuwsockets_h3.cpp +++ b/src/uws_sys/libuwsockets_h3.cpp @@ -50,10 +50,8 @@ uws_h3_app_t* uws_h3_create_app(struct us_bun_socket_context_options_t options, } void uws_h3_app_destroy(uws_h3_app_t* app) { delete (H3App*)app; } -bool uws_h3_constructor_failed(uws_h3_app_t* app) { return !app || ((H3App*)app)->constructorFailed(); } void uws_h3_app_close(uws_h3_app_t* app) { ((H3App*)app)->close(); } void uws_h3_app_clear_routes(uws_h3_app_t* app) { ((H3App*)app)->clearRoutes(); } -void* uws_h3_get_native_handle(uws_h3_app_t* app) { return ((H3App*)app)->getNativeHandle(); } bool uws_h3_app_add_server_name(uws_h3_app_t* app, const char* hostname, struct us_bun_socket_context_options_t options) @@ -177,8 +175,6 @@ bool uws_h3_res_write(uws_h3_res_t* res, const char* data, size_t* length) return ok; } -uint64_t uws_h3_res_get_write_offset(uws_h3_res_t* res) { return ((Http3Response*)res)->getWriteOffset(); } -void uws_h3_res_override_write_offset(uws_h3_res_t* res, uint64_t off) { ((Http3Response*)res)->overrideWriteOffset(off); } bool uws_h3_res_has_responded(uws_h3_res_t* res) { return ((Http3Response*)res)->hasResponded(); } size_t uws_h3_res_get_buffered_amount(uws_h3_res_t* res) { return ((Http3Response*)res)->getBufferedAmount(); } @@ -189,10 +185,6 @@ void uws_h3_res_end_sendfile(uws_h3_res_t* res, uint64_t, bool close) /* sendfile path falls back to plain end-of-stream over QUIC. */ ((Http3Response*)res)->sendTerminatingChunk(close); } -void uws_h3_res_prepare_for_sendfile(uws_h3_res_t*) {} -bool uws_h3_res_is_connect_request(uws_h3_res_t*) { return false; } -void* uws_h3_res_get_native_handle(uws_h3_res_t* res) { return res; } -void* uws_h3_res_get_socket_data(uws_h3_res_t* res) { return ((Http3Response*)res)->getSocketData(); } void uws_h3_res_on_writable(uws_h3_res_t* res, bool (*h)(uws_h3_res_t*, uint64_t, void*), void* opt) { @@ -222,8 +214,6 @@ void uws_h3_res_cork(uws_h3_res_t* res, void* ctx, void (*corker)(void*)) { ((Http3Response*)res)->cork([ctx, corker]() { corker(ctx); }); } -void uws_h3_res_uncork(uws_h3_res_t*) {} -bool uws_h3_res_is_corked(uws_h3_res_t*) { return false; } uint64_t uws_h3_res_get_remote_address_info(uws_h3_res_t* res, const char** dest, int* port, bool* is_ipv6) { @@ -258,8 +248,6 @@ uint64_t uws_h3_res_get_remote_address_info(uws_h3_res_t* res, const char** dest /* ───── request ───── */ -bool uws_h3_req_is_ancient(uws_h3_req_t*) { return false; } -bool uws_h3_req_get_yield(uws_h3_req_t* req) { return ((Http3Request*)req)->getYield(); } void uws_h3_req_set_yield(uws_h3_req_t* req, bool y) { ((Http3Request*)req)->setYield(y); } /* The FFI contract requires a non-null pointer; a default- @@ -285,23 +273,6 @@ size_t uws_h3_req_get_header(uws_h3_req_t* req, const char* lower, size_t lower_ return ffi_sv(((Http3Request*)req)->getHeader(sv(lower, lower_len)), dest); } -void uws_h3_req_for_each_header(uws_h3_req_t* req, - void (*cb)(const char*, size_t, const char*, size_t, void*), - void* user_data) -{ - ((Http3Request*)req)->forEachHeader([cb, user_data](std::string_view name, std::string_view value) { - cb(name.empty() ? "" : name.data(), name.length(), - value.empty() ? "" : value.data(), value.length(), user_data); - }); -} - -size_t uws_h3_req_get_query(uws_h3_req_t* req, const char* key, size_t key_len, const char** dest) -{ - return ffi_sv(key ? ((Http3Request*)req)->getQuery(sv(key, key_len)) - : ((Http3Request*)req)->getQuery(), - dest); -} - size_t uws_h3_req_get_parameter(uws_h3_req_t* req, unsigned short index, const char** dest) { return ffi_sv(((Http3Request*)req)->getParameter(index), dest); diff --git a/src/uws_sys/socket.rs b/src/uws_sys/socket.rs index 394ab83eaa94..a41285a170bb 100644 --- a/src/uws_sys/socket.rs +++ b/src/uws_sys/socket.rs @@ -696,13 +696,6 @@ impl NewSocketHandler { socket: InternalSocket::UpgradedDuplex(d), } } - #[cfg(windows)] - #[inline] - pub fn from_named_pipe(p: *mut WindowsNamedPipe) -> Self { - Self { - socket: InternalSocket::Pipe(p), - } - } /// Wrap an already-open fd. Ext stores `*mut This`; the socket is linked /// into `g` with kind `k`. Port of `NewSocketHandler.fromFd`. diff --git a/test/internal/source-lints/dead-symbols-uws-webcore-crash-scripts.test.ts b/test/internal/source-lints/dead-symbols-uws-webcore-crash-scripts.test.ts new file mode 100644 index 000000000000..4de459e217ba --- /dev/null +++ b/test/internal/source-lints/dead-symbols-uws-webcore-crash-scripts.test.ts @@ -0,0 +1,148 @@ +// Guards against reintroduction of symbols removed as dead code from +// bun_uws_sys (unused C API wrappers and their Rust declarations), the +// C++ JSC bindings (DOMConstructors entries, stray macros and forward +// declarations), bun_crash_handler (the error-return-trace apparatus, +// which Rust cannot produce), bun_collections, the bun:sql builtin, and the +// retired scripts/clippy-loop tooling. +// Each entry was verified to have zero references across src/, scripts/, +// test/, vendor/, and regenerated build/debug/codegen/ output before deletion, +// and the removal was validated by `cargo check` on all 10 CI target triples +// plus a full `bun bd` build. +// +// This is a source-tree lint: it reads files from src/ and does not touch the +// built binary, so it belongs in test/internal/source-lints/ per the README. +// +// The Rust checks read the working tree. The C++/JS checks read the committed +// tree (HEAD) instead: `git stash` round-trips can temporarily restore files a +// branch deletes (see the same note in dead-code-escapes.test.ts), and those +// strays must not fail the lint. CI runs against the committed tree, so HEAD +// is what matters. + +import { expect, test } from "bun:test"; +import { readFileSync } from "node:fs"; +import path from "node:path"; + +const repoRoot = path.resolve(import.meta.dir, "..", "..", ".."); + +function src(p: string): string { + return readFileSync(path.join(repoRoot, p), "utf8"); +} + +function headFile(p: string): string { + const r = Bun.spawnSync({ + cmd: ["git", "-C", repoRoot, "show", `HEAD:${p}`], + stdout: "pipe", + stderr: "pipe", + }); + if (r.exitCode !== 0) { + throw new Error(`git show HEAD:${p} failed: ${r.stderr.toString()}`); + } + return r.stdout.toString(); +} + +function existsInHead(p: string): boolean { + const r = Bun.spawnSync({ + cmd: ["git", "-C", repoRoot, "ls-tree", "--name-only", "HEAD", "--", p], + stdout: "pipe", + stderr: "pipe", + }); + if (r.exitCode !== 0) { + throw new Error(`git ls-tree HEAD -- ${p} failed: ${r.stderr.toString()}`); + } + return r.stdout.toString().trim().length > 0; +} + +test("dead Rust symbols (uws_sys, crash_handler, collections) do not reappear", () => { + const checks: Array<[string, RegExp]> = [ + // uws_sys: extern declarations whose C side had no callers, and safe + // wrappers nothing invoked (the *_with_options counterparts are the live + // paths). + ["src/uws_sys/WebSocket.rs", /uws_ws_send_fragment|uws_ws_send_first_fragment|uws_ws_get_remote_address_as_text/], + ["src/uws_sys/Response.rs", /override_write_offset/], + ["src/uws_sys/h3.rs", /override_write_offset/], + ["src/uws_sys/Loop.rs", /add_pre_handler|add_post_handler|uws_loop_addPreHandler|uws_loop_addPostHandler/], + ["src/uws_sys/socket.rs", /\bfrom_named_pipe\b/], + ["src/uws_sys/lib.rs", /us_fault_clear\b|LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE/], + // crash_handler: error-return tracing is a Zig feature Rust has no + // equivalent of; the whole reporting path was unreachable behind a + // `const false`. + [ + "src/crash_handler/lib.rs", + /error_return_trace|VERBOSE_ERROR_TRACE|HAVE_ERROR_RETURN_TRACING|TraceSeed::ErrorReturn/, + ], + // Nothing Display-formats a StackLine (the symbolizer formats its + // .address field directly). + ["src/crash_handler/lib.rs", /impl fmt::Display for StackLine/], + // handle_oom arms for crate::Error / bare AllocError: the only importer + // (js_parser scan_imports) threads Result. + ["src/crash_handler/handle_oom.rs", /impl HandleOom for (Error|AllocError)|Result/], + // The --verbose-error-trace debug flag only fed the deleted trace path. + ["src/runtime/cli/Arguments.rs", /verbose-error-trace|maybe_verbose_error_trace/], + // All PriorityQueue construction goes through ::init. + ["src/collections/lib.rs", /impl Default for PriorityQueue/], + ]; + const resurrected = checks.filter(([file, re]) => re.test(src(file))).map(([file, re]) => `${file}: ${re.source}`); + expect(resurrected).toEqual([]); +}); + +test("dead uws_sys C wrappers do not reappear", () => { + const checks: Array<[string, RegExp]> = [ + // Wrappers with no Rust-side declaration (or an unused one); the + // `(`-anchored patterns deliberately miss the live *_with_options names. + [ + "src/uws_sys/libuwsockets.cpp", + /uws_ws_send\(|uws_ws_publish\(|uws_app_listen_domain\(|uws_add_server_name\(|uws_remove_server_name\(|uws_missing_server_name\(/, + ], + [ + "src/uws_sys/libuwsockets.cpp", + /uws_constructor_failed|uws_get_native_handle|uws_res_get_write_offset|uws_res_override_write_offset|uws_res_get_socket_data/, + ], + [ + "src/uws_sys/libuwsockets.cpp", + /uws_req_is_ancient|uws_req_get_yield|uws_req_for_each_header|uws_req_get_query|uws_loop_addPostHandler|uws_loop_removePostHandler|uws_loop_removePreHandler/, + ], + [ + "src/uws_sys/libuwsockets_h3.cpp", + /uws_h3_constructor_failed|uws_h3_get_native_handle|uws_h3_res_get_write_offset|uws_h3_res_override_write_offset|uws_h3_res_uncork|uws_h3_res_is_corked|uws_h3_req_for_each_header|uws_h3_req_get_query/, + ], + // Handler typedefs only the deleted wrappers used. + ["src/uws_sys/_libusockets.h", /uws_missing_server_handler|uws_get_headers_server_handler/], + ]; + const resurrected = checks + .filter(([file, re]) => re.test(headFile(file))) + .map(([file, re]) => `${file}: ${re.source}`); + expect(resurrected).toEqual([]); +}); + +test("dead C++ bindings do not reappear", () => { + const checks: Array<[string, RegExp]> = [ + // DOMConstructors.h is trimmed to the constructors bun actually wires; + // these are sentinels for the ~800 WebKit-inherited entries. + ["src/jsc/bindings/webcore/DOMConstructors.h", /^\s*(Touch|ApplePaySession|GPUDevice|WebKitMediaKeys),$/m], + ["src/jsc/bindings/webcore/DOMConstructors.h", /numberOfDOMConstructorsBase|bunExtraConstructors/], + ["src/jsc/bindings/napi.h", /NAPI_PERISH/], + ["src/jsc/bindings/dh-primes.h", /\b(OPENSSL_ARRAY_SIZE|TOBN)\b/], + ["src/jsc/bindings/JSDOMWrapper.h", /hasCustomPtrTraits/], + ["src/jsc/bindings/webcore/JSPerformance.h", /class JSPerformanceObject;/], + ["src/jsc/bindings/webcore/SerializedScriptValue.h", /class MemoryHandle;|class FragmentedSharedBuffer;/], + ["src/jsc/bindings/node/crypto/KeyObject.h", /createJwk/], + // Commented-out $create*Error helpers native code never called. + ["src/js/bun/sql.ts", /\$createPostgresError|\$createSQLiteError|\$createSQLError/], + ]; + const resurrected = checks + .filter(([file, re]) => re.test(headFile(file))) + .map(([file, re]) => `${file}: ${re.source}`); + expect(resurrected).toEqual([]); +}); + +test("deleted files stay deleted", () => { + const gone = [ + // Orphan LLVM bitcode blob with no build-system reference. + "src/base64/neonbase64", + // One-shot tooling for the completed 2026-05 clippy campaign. + "scripts/clippy-loop/harvest.ts", + "scripts/clippy-loop/collect.sh", + "scripts/clippy-loop/apply-patches.ts", + ]; + expect(gone.filter(existsInHead)).toEqual([]); +});