mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
## Summary Fixes all oxlint `no-unused-expressions` violations across the codebase by: - Adding an oxlint override to disable the rule for `src/js/builtins/**`, where special syntax markers like `$getter`, `$constructor`, etc. are intentionally used as standalone expressions - Converting short-circuit expressions (`condition && fn()`) to proper if statements for improved code clarity - Wrapping intentional property access side effects (e.g., `this.stdio;`, `err.stack;`) with the `void` operator - Converting ternary expressions used for control flow to if/else statements ## Test plan - [x] `bun lint` passes with no errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
217 lines
5.2 KiB
TypeScript
217 lines
5.2 KiB
TypeScript
// Users may override the global fetch implementation, so we need to ensure these are the originals.
|
|
const bindings = $cpp("NodeFetch.cpp", "createNodeFetchInternalBinding");
|
|
const WebResponse: typeof globalThis.Response = bindings[0];
|
|
const WebRequest: typeof globalThis.Request = bindings[1];
|
|
const Blob: typeof globalThis.Blob = bindings[2];
|
|
const WebHeaders: typeof globalThis.Headers = bindings[3];
|
|
const FormData: typeof globalThis.FormData = bindings[4];
|
|
const File: typeof globalThis.File = bindings[5];
|
|
const nativeFetch = Bun.fetch;
|
|
|
|
// node-fetch extends from URLSearchParams in their implementation...
|
|
// https://github.com/node-fetch/node-fetch/blob/8b3320d2a7c07bce4afc6b2bf6c3bbddda85b01f/src/headers.js#L44
|
|
class Headers extends WebHeaders {
|
|
raw() {
|
|
const obj = this.toJSON();
|
|
for (const key in obj) {
|
|
const val = obj[key];
|
|
if (!$isJSArray(val)) {
|
|
// They must all be arrays.
|
|
obj[key] = [val];
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
// node-fetch inherits this due to URLSearchParams.
|
|
// it also throws if you try to use it.
|
|
sort() {
|
|
throw new TypeError("Expected this to be instanceof URLSearchParams");
|
|
}
|
|
}
|
|
|
|
const kHeaders = Symbol("kHeaders");
|
|
const kBody = Symbol("kBody");
|
|
const HeadersPrototype = Headers.prototype;
|
|
|
|
class Response extends WebResponse {
|
|
[kBody]: any;
|
|
[kHeaders];
|
|
|
|
constructor(body, init) {
|
|
const { Readable, Stream } = require("node:stream");
|
|
if (body && typeof body === "object" && (body instanceof Stream || body instanceof Readable)) {
|
|
body = Readable.toWeb(body);
|
|
}
|
|
|
|
super(body, init);
|
|
}
|
|
|
|
get body() {
|
|
let body = this[kBody];
|
|
if (!body) {
|
|
var web = super.body;
|
|
if (!web) return null;
|
|
body = this[kBody] = new (require("internal/webstreams_adapters")._ReadableFromWeb)({}, web);
|
|
}
|
|
|
|
return body;
|
|
}
|
|
|
|
get headers() {
|
|
return (this[kHeaders] ??= Object.setPrototypeOf(super.headers, HeadersPrototype) as any);
|
|
}
|
|
|
|
clone() {
|
|
return Object.setPrototypeOf(super.clone(this), ResponsePrototype);
|
|
}
|
|
|
|
async arrayBuffer() {
|
|
// load the getter
|
|
void this.body;
|
|
return await super.arrayBuffer();
|
|
}
|
|
|
|
async blob() {
|
|
// load the getter
|
|
void this.body;
|
|
return await super.blob();
|
|
}
|
|
|
|
async formData() {
|
|
// load the getter
|
|
void this.body;
|
|
return await super.formData();
|
|
}
|
|
|
|
async json() {
|
|
// load the getter
|
|
void this.body;
|
|
return await super.json();
|
|
}
|
|
|
|
// This is a deprecated function in node-fetch
|
|
// but is still used by some libraries and frameworks (like Astro)
|
|
async buffer() {
|
|
// load the getter
|
|
void this.body;
|
|
return new $Buffer(await super.arrayBuffer());
|
|
}
|
|
|
|
async text() {
|
|
// load the getter
|
|
void this.body;
|
|
return await super.text();
|
|
}
|
|
|
|
get type() {
|
|
if (!super.ok) {
|
|
return "error";
|
|
}
|
|
|
|
return "default";
|
|
}
|
|
}
|
|
var ResponsePrototype = Response.prototype;
|
|
|
|
const kUrl = Symbol("kUrl");
|
|
|
|
class Request extends WebRequest {
|
|
[kUrl]?: string;
|
|
|
|
constructor(input, init) {
|
|
// node-fetch is relaxed with the URL, for example, it allows "/" as a valid URL.
|
|
// If it's not a valid URL, use a placeholder URL during construction.
|
|
// See: https://github.com/oven-sh/bun/issues/4947
|
|
if (typeof input === "string" && !URL.canParse(input)) {
|
|
super(new URL(input, "http://localhost/"), init);
|
|
this[kUrl] = input;
|
|
} else {
|
|
super(input, init);
|
|
}
|
|
}
|
|
|
|
get url() {
|
|
return this[kUrl] ?? super.url;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* `node-fetch` works like the browser-fetch API, except it's a little more strict on some features,
|
|
* and uses node streams instead of web streams.
|
|
*
|
|
* It's overall a positive on speed to override the implementation, since most people will use something
|
|
* like `.json()` or `.text()`, which is faster in Bun's native fetch, vs `node-fetch` going
|
|
* through `node:http`, a node stream, then processing the data.
|
|
*/
|
|
async function fetch(
|
|
// eslint-disable-next-line no-unused-vars
|
|
url: any,
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
init?: RequestInit & { body?: any },
|
|
) {
|
|
// Since `body` accepts async iterables
|
|
// We don't need to convert the Readable body into a ReadableStream.
|
|
const response = await nativeFetch.$apply(undefined, arguments);
|
|
Object.setPrototypeOf(response, ResponsePrototype);
|
|
return response;
|
|
}
|
|
|
|
class AbortError extends DOMException {
|
|
constructor(message) {
|
|
super(message, "AbortError");
|
|
}
|
|
}
|
|
|
|
class FetchBaseError extends Error {
|
|
type: string;
|
|
|
|
constructor(message, type) {
|
|
super(message);
|
|
this.type = type;
|
|
}
|
|
}
|
|
|
|
class FetchError extends FetchBaseError {
|
|
constructor(message, type, systemError) {
|
|
super(message, type);
|
|
this.code = systemError?.code;
|
|
}
|
|
}
|
|
|
|
function blobFrom(path, options) {
|
|
return Promise.$resolve(Bun.file(path, options));
|
|
}
|
|
|
|
function blobFromSync(path, options) {
|
|
return Bun.file(path, options);
|
|
}
|
|
|
|
var fileFrom = blobFrom;
|
|
var fileFromSync = blobFromSync;
|
|
|
|
function isRedirect(code) {
|
|
return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
|
|
}
|
|
|
|
export default Object.assign(fetch, {
|
|
AbortError,
|
|
Blob,
|
|
FetchBaseError,
|
|
FetchError,
|
|
File,
|
|
FormData,
|
|
Headers,
|
|
Request,
|
|
Response,
|
|
blobFrom,
|
|
blobFromSync,
|
|
fileFrom,
|
|
fileFromSync,
|
|
isRedirect,
|
|
fetch,
|
|
default: fetch,
|
|
});
|