From 032713c58cf76f822cb6901e1bd303edee6bc769 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sat, 19 Apr 2025 05:41:34 -0700 Subject: [PATCH] Fix several lints (#19121) --- .github/workflows/lint.yml | 5 +- .vscode/settings.json | 2 + oxlint.json | 38 +- package.json | 2 +- .../client/JavaScriptSyntaxHighlighter.ts | 2 +- src/bake/client/overlay.ts | 2 +- src/bun.js/bindings/ZigGlobalObject.cpp | 13 - src/bun.js/node/node.classes.ts | 174 +++--- src/bun.js/webcore/response.classes.ts | 35 +- src/codegen/bundle-modules.ts | 7 +- src/codegen/class-definitions.ts | 11 +- src/codegen/generate-classes.ts | 231 ++++++++ src/codegen/generate-node-errors.ts | 38 +- src/js/builtins.d.ts | 131 ++++- src/js/builtins/BundlerPlugin.ts | 9 +- src/js/builtins/CommonJS.ts | 56 +- src/js/builtins/ConsoleObject.ts | 12 +- src/js/builtins/EventSource.ts | 498 ------------------ src/js/builtins/NodeModuleObject.ts | 13 +- src/js/builtins/ProcessObjectInternals.ts | 6 +- .../builtins/ReadableByteStreamController.ts | 6 +- .../builtins/ReadableByteStreamInternals.ts | 18 +- src/js/builtins/ReadableStreamInternals.ts | 92 ++-- src/js/builtins/shell.ts | 37 +- src/js/bun/sql.ts | 62 ++- src/js/bun/sqlite.ts | 45 +- src/js/internal/assert/myers_diff.ts | 2 +- src/js/internal/assert/utils.ts | 2 +- src/js/internal/cluster/RoundRobinHandle.ts | 2 +- src/js/internal/cluster/child.ts | 2 +- src/js/internal/cluster/primary.ts | 2 +- src/js/internal/debugger.ts | 6 +- src/js/internal/errors.ts | 2 +- src/js/internal/fs/streams.ts | 4 +- src/js/internal/html.ts | 4 +- src/js/internal/shared.ts | 2 +- src/js/internal/streams/duplex.ts | 2 +- src/js/internal/streams/native-readable.ts | 2 +- src/js/internal/streams/readable.ts | 12 +- src/js/internal/streams/transform.ts | 2 +- src/js/internal/streams/writable.ts | 2 +- src/js/internal/tty.ts | 2 +- src/js/internal/util/inspect.js | 12 - src/js/internal/validators.ts | 3 - src/js/internal/webstreams_adapters.ts | 12 +- src/js/node/async_hooks.ts | 8 +- src/js/node/child_process.ts | 9 +- src/js/node/dgram.ts | 34 +- src/js/node/events.ts | 8 +- src/js/node/fs.promises.ts | 49 +- src/js/node/fs.ts | 54 +- src/js/node/http.ts | 2 +- src/js/node/https.ts | 1 - src/js/node/net.ts | 30 +- src/js/node/os.ts | 2 +- src/js/node/perf_hooks.ts | 20 +- src/js/node/readline.ts | 8 - src/js/node/repl.ts | 15 - src/js/node/test.ts | 221 +------- src/js/node/timers.promises.ts | 2 +- src/js/node/timers.ts | 2 +- src/js/node/url.ts | 2 - src/js/node/util.ts | 1 - src/js/node/v8.ts | 2 +- src/js/node/wasi.ts | 11 +- src/js/node/zlib.ts | 22 +- src/js/thirdparty/depd.js | 32 -- src/js/thirdparty/undici.js | 7 +- src/js/thirdparty/vercel_fetch.js | 12 +- src/js/thirdparty/ws.js | 10 +- 70 files changed, 906 insertions(+), 1280 deletions(-) delete mode 100644 src/js/builtins/EventSource.ts delete mode 100644 src/js/thirdparty/depd.js diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 33ef015a53..474bfc17ad 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,8 +5,7 @@ on: workflow_dispatch: env: - BUN_VERSION: "1.2.0" - OXLINT_VERSION: "0.15.0" + BUN_VERSION: "1.2.10" jobs: lint-js: @@ -19,4 +18,4 @@ jobs: with: bun-version: ${{ env.BUN_VERSION }} - name: Lint - run: bunx oxlint --config oxlint.json --quiet --format github + run: bun lint diff --git a/.vscode/settings.json b/.vscode/settings.json index a6ec222240..a5ecae51f0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -146,6 +146,8 @@ "*.mdc": "markdown", "array": "cpp", "ios": "cpp", + "oxlint.json": "jsonc", + "bun.lock": "jsonc", }, "C_Cpp.files.exclude": { "**/.vscode": true, diff --git a/oxlint.json b/oxlint.json index 352d94e287..60d61d72fb 100644 --- a/oxlint.json +++ b/oxlint.json @@ -1,10 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/refs/heads/main/npm/oxlint/configuration_schema.json", "categories": { - "correctness": "warn" // TODO: gradually fix bugs and turn this to error + "correctness": "error" }, "rules": { - "const-comparisons": "off", // TODO: there's a bug when comparing private identifiers. Re-enable once it's fixed. + "const-comparisons": "error", "no-cond-assign": "error", "no-const-assign": "error", "no-debugger": "error", @@ -13,12 +13,35 @@ "no-empty-pattern": "error", "import/no-duplicates": "error", - "no-useless-escape": "off" // there's a lot of these. Should be fixed eventually. + "no-control-regex": "off", + + "no-useless-escape": "off", + "no-this-alias": "off", // many intentional this aliases + "triple-slash-reference": "off", // many intentional triple slash references + + // This rule is dumb. + // Array.from is MUCH slower than new Array(size). + "no-new-array": "off", + + // We have custom thenables. This is not a bug. + "no-thenable": "off", + + "no-undef-init": "error", + + // We use this in some cases. The ordering is deliberate. + "no-unsafe-finally": "off", + + // We use !!$debug to check if the debugger is enabled. + // Boolean() is also generally slower than !!. + "no-extra-boolean-cast": "off", + + // Eslint is not a type checker. + "no-throw-literal": "off" }, "ignorePatterns": [ "vendor", "build", - "test/snapshots/**", + "bench", "bench/react-hello-world/*.js", "bun.lock", @@ -32,8 +55,13 @@ "test/bundler/transpiler/with-statement-works.js", // parser doesn't allow `with` statement "test/js/node/module/extensions-fixture", // these files are not meant to be linted "test/cli/run/module-type-fixture", - "test/bundler/transpiler/with-statement-works.js" // parser doesn't allow `with` statement + "test/bundler/transpiler/with-statement-works.js", // parser doesn't allow `with` statement + + // TODO: fix these + "src/js/node/http2.ts", + "src/js/node/http.ts" ], + "overrides": [ { "files": ["test/**", "examples/**", "packages/bun-internal/test/runners/**"], diff --git a/package.json b/package.json index 7ae7d3612e..bc55758c49 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "fmt": "bun run prettier", "fmt:cpp": "bun run clang-format", "fmt:zig": "bun run zig-format", - "lint": "oxlint --config oxlint.json", + "lint": "bunx oxlint --config=oxlint.json --format=github src/js", "lint:fix": "oxlint --config oxlint.json --fix", "test": "node scripts/runner.node.mjs --exec-path ./build/debug/bun-debug", "test:release": "node scripts/runner.node.mjs --exec-path ./build/release/bun", diff --git a/src/bake/client/JavaScriptSyntaxHighlighter.ts b/src/bake/client/JavaScriptSyntaxHighlighter.ts index 5099927cc6..474ea5f9e5 100644 --- a/src/bake/client/JavaScriptSyntaxHighlighter.ts +++ b/src/bake/client/JavaScriptSyntaxHighlighter.ts @@ -806,7 +806,7 @@ export class DraculaSyntaxHighlighter { // Check for NPM token if (str.startsWith("npm_") && str.length === 68) { const isValidTokenChar = (c: string) => this.isIdentifierPart(c); - return [...str.slice(4)].every(isValidTokenChar); + return str.slice(4).every(isValidTokenChar); } return false; diff --git a/src/bake/client/overlay.ts b/src/bake/client/overlay.ts index c565916ca3..4e16f2f284 100644 --- a/src/bake/client/overlay.ts +++ b/src/bake/client/overlay.ts @@ -514,7 +514,7 @@ function updateRuntimeErrorOverlay(err: RuntimeError) { } dom.appendChild( - elem("div", { class: "r-error-trace" }, [...trace.map(frame => renderTraceFrame(frame, "trace-frame"))]), + elem("div", { class: "r-error-trace" }, trace.map(frame => renderTraceFrame(frame, "trace-frame"))), ); domErrorContent.appendChild(dom); } diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 3e49584426..0a69256ca2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -3654,19 +3654,6 @@ JSC_DEFINE_CUSTOM_GETTER(getConsoleStderr, (JSGlobalObject * globalObject, Encod return JSValue::encode(stderrValue); } -JSC_DEFINE_CUSTOM_SETTER(EventSource_setter, - (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, - JSC::EncodedJSValue value, JSC::PropertyName property)) -{ - if (JSValue::decode(thisValue) != globalObject) { - return false; - } - - auto& vm = JSC::getVM(globalObject); - globalObject->putDirect(vm, property, JSValue::decode(value), 0); - return true; -} - JSC_DEFINE_HOST_FUNCTION(jsFunctionToClass, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { // Mimick the behavior of class Foo {} for a regular JSFunction. diff --git a/src/bun.js/node/node.classes.ts b/src/bun.js/node/node.classes.ts index 72872c1822..09f49b72ca 100644 --- a/src/bun.js/node/node.classes.ts +++ b/src/bun.js/node/node.classes.ts @@ -220,96 +220,96 @@ export default [ klass: {}, proto: { - appendFile: { fn: "appendFile", length: 4 }, - appendFileSync: { fn: "appendFileSync", length: 3 }, - access: { fn: "access", length: 3 }, - accessSync: { fn: "accessSync", length: 2 }, - chown: { fn: "chown", length: 4 }, - chownSync: { fn: "chownSync", length: 3 }, - chmod: { fn: "chmod", length: 3 }, - chmodSync: { fn: "chmodSync", length: 2 }, - close: { fn: "close", length: 1 }, - closeSync: { fn: "closeSync", length: 1 }, - copyFile: { fn: "copyFile", length: 4 }, - copyFileSync: { fn: "copyFileSync", length: 3 }, + appendFile: { async: true, fn: "appendFile", length: 4 }, + appendFileSync: { async: false, fn: "appendFileSync", length: 3 }, + access: { async: true, fn: "access", length: 3 }, + accessSync: { async: false, fn: "accessSync", length: 2 }, + chown: { async: true, fn: "chown", length: 4 }, + chownSync: { async: false, fn: "chownSync", length: 3 }, + chmod: { async: true, fn: "chmod", length: 3 }, + chmodSync: { async: false, fn: "chmodSync", length: 2 }, + close: { async: true, fn: "close", length: 1 }, + closeSync: { async: false, fn: "closeSync", length: 1 }, + copyFile: { async: true, fn: "copyFile", length: 4 }, + copyFileSync: { async: false, fn: "copyFileSync", length: 3 }, // TODO: - cp: { fn: "cp", length: 2 }, - cpSync: { fn: "cpSync", length: 2 }, + cp: { async: true, fn: "cp", length: 2 }, + cpSync: { async: false, fn: "cpSync", length: 2 }, - exists: { fn: "exists", length: 2 }, - existsSync: { fn: "existsSync", length: 1 }, - fchown: { fn: "fchown", length: 4 }, - fchownSync: { fn: "fchownSync", length: 3 }, - fchmod: { fn: "fchmod", length: 3 }, - fchmodSync: { fn: "fchmodSync", length: 2 }, - fdatasync: { fn: "fdatasync", length: 2 }, - fdatasyncSync: { fn: "fdatasyncSync", length: 1 }, - fstat: { fn: "fstat", length: 1 }, - fstatSync: { fn: "fstatSync", length: 1 }, - fsync: { fn: "fsync", length: 2 }, - fsyncSync: { fn: "fsyncSync", length: 1 }, - ftruncate: { fn: "ftruncate", length: 1 }, - ftruncateSync: { fn: "ftruncateSync", length: 1 }, - futimes: { fn: "futimes", length: 4 }, - futimesSync: { fn: "futimesSync", length: 3 }, - lchown: { fn: "lchown", length: 4 }, - lchownSync: { fn: "lchownSync", length: 3 }, - lchmod: { fn: "lchmod", length: 3 }, - lchmodSync: { fn: "lchmodSync", length: 2 }, - link: { fn: "link", length: 3 }, - linkSync: { fn: "linkSync", length: 2 }, - lstat: { fn: "lstat", length: 1 }, - lstatSync: { fn: "lstatSync", length: 1 }, - lutimes: { fn: "lutimes", length: 4 }, - lutimesSync: { fn: "lutimesSync", length: 3 }, - mkdir: { fn: "mkdir", length: 3 }, - mkdirSync: { fn: "mkdirSync", length: 2 }, - mkdtemp: { fn: "mkdtemp", length: 3 }, - mkdtempSync: { fn: "mkdtempSync", length: 2 }, - open: { fn: "open", length: 4 }, - openSync: { fn: "openSync", length: 3 }, - readdir: { fn: "readdir", length: 3 }, - readdirSync: { fn: "readdirSync", length: 2 }, - read: { fn: "read", length: 6 }, - readSync: { fn: "readSync", length: 5 }, - readv: { fn: "readv", length: 4 }, - readvSync: { fn: "readvSync", length: 3 }, - readFile: { fn: "readFile", length: 3 }, - readFileSync: { fn: "readFileSync", length: 2 }, - readlink: { fn: "readlink", length: 3 }, - readlinkSync: { fn: "readlinkSync", length: 2 }, - realpath: { fn: "realpath", length: 3 }, - realpathSync: { fn: "realpathSync", length: 2 }, - rename: { fn: "rename", length: 3 }, - renameSync: { fn: "renameSync", length: 2 }, - rm: { fn: "rm", length: 3 }, - rmSync: { fn: "rmSync", length: 2 }, - rmdir: { fn: "rmdir", length: 3 }, - rmdirSync: { fn: "rmdirSync", length: 2 }, - stat: { fn: "stat", length: 1 }, - statfs: { fn: "statfs", length: 2 }, - statSync: { fn: "statSync", length: 1 }, - statfsSync: { fn: "statfsSync", length: 2 }, - symlink: { fn: "symlink", length: 4 }, - symlinkSync: { fn: "symlinkSync", length: 3 }, - truncate: { fn: "truncate", length: 3 }, - truncateSync: { fn: "truncateSync", length: 2 }, - unwatchFile: { fn: "unwatchFile", length: 2 }, - unlink: { fn: "unlink", length: 2 }, - unlinkSync: { fn: "unlinkSync", length: 1 }, - utimes: { fn: "utimes", length: 4 }, - utimesSync: { fn: "utimesSync", length: 3 }, - watch: { fn: "watch", length: 3 }, - watchFile: { fn: "watchFile", length: 3 }, - writeFile: { fn: "writeFile", length: 4 }, - writeFileSync: { fn: "writeFileSync", length: 3 }, - write: { fn: "write", length: 6 }, - writeSync: { fn: "writeSync", length: 5 }, - writev: { fn: "writev", length: 4 }, - writevSync: { fn: "writevSync", length: 3 }, - realpathNative: { fn: "realpathNative", length: 3 }, - realpathNativeSync: { fn: "realpathNativeSync", length: 3 }, + exists: { async: true, fn: "exists", length: 2 }, + existsSync: { async: false, fn: "existsSync", length: 1 }, + fchown: { async: true, fn: "fchown", length: 4 }, + fchownSync: { async: false, fn: "fchownSync", length: 3 }, + fchmod: { async: true, fn: "fchmod", length: 3 }, + fchmodSync: { async: false, fn: "fchmodSync", length: 2 }, + fdatasync: { async: false, fn: "fdatasync", length: 2 }, + fdatasyncSync: { async: false, fn: "fdatasyncSync", length: 1 }, + fstat: { async: true, fn: "fstat", length: 1 }, + fstatSync: { async: false, fn: "fstatSync", length: 1 }, + fsync: { async: false, fn: "fsync", length: 2 }, + fsyncSync: { async: false, fn: "fsyncSync", length: 1 }, + ftruncate: { async: true, fn: "ftruncate", length: 1 }, + ftruncateSync: { async: false, fn: "ftruncateSync", length: 1 }, + futimes: { async: true, fn: "futimes", length: 4 }, + futimesSync: { async: false, fn: "futimesSync", length: 3 }, + lchown: { async: true, fn: "lchown", length: 4 }, + lchownSync: { async: false, fn: "lchownSync", length: 3 }, + lchmod: { async: true, fn: "lchmod", length: 3 }, + lchmodSync: { async: false, fn: "lchmodSync", length: 2 }, + link: { async: true, fn: "link", length: 3 }, + linkSync: { async: false, fn: "linkSync", length: 2 }, + lstat: { async: true, fn: "lstat", length: 1 }, + lstatSync: { async: false, fn: "lstatSync", length: 1 }, + lutimes: { async: true, fn: "lutimes", length: 4 }, + lutimesSync: { async: false, fn: "lutimesSync", length: 3 }, + mkdir: { async: true, fn: "mkdir", length: 3 }, + mkdirSync: { async: false, fn: "mkdirSync", length: 2 }, + mkdtemp: { async: true, fn: "mkdtemp", length: 3 }, + mkdtempSync: { async: false, fn: "mkdtempSync", length: 2 }, + open: { async: true, fn: "open", length: 4 }, + openSync: { async: false, fn: "openSync", length: 3 }, + readdir: { async: true, fn: "readdir", length: 3 }, + readdirSync: { async: false, fn: "readdirSync", length: 2 }, + read: { async: true, fn: "read", length: 6 }, + readSync: { async: false, fn: "readSync", length: 5 }, + readv: { async: true, fn: "readv", length: 4 }, + readvSync: { async: false, fn: "readvSync", length: 3 }, + readFile: { async: true, fn: "readFile", length: 3 }, + readFileSync: { async: false, fn: "readFileSync", length: 2 }, + readlink: { async: true, fn: "readlink", length: 3 }, + readlinkSync: { async: false, fn: "readlinkSync", length: 2 }, + realpath: { async: true, fn: "realpath", length: 3 }, + realpathSync: { async: false, fn: "realpathSync", length: 2 }, + rename: { async: true, fn: "rename", length: 3 }, + renameSync: { async: false, fn: "renameSync", length: 2 }, + rm: { async: true, fn: "rm", length: 3 }, + rmSync: { async: false, fn: "rmSync", length: 2 }, + rmdir: { async: true, fn: "rmdir", length: 3 }, + rmdirSync: { async: false, fn: "rmdirSync", length: 2 }, + stat: { async: true, fn: "stat", length: 1 }, + statfs: { async: true, fn: "statfs", length: 2 }, + statSync: { async: false, fn: "statSync", length: 1 }, + statfsSync: { async: false, fn: "statfsSync", length: 2 }, + symlink: { async: true, fn: "symlink", length: 4 }, + symlinkSync: { async: false, fn: "symlinkSync", length: 3 }, + truncate: { async: true, fn: "truncate", length: 3 }, + truncateSync: { async: false, fn: "truncateSync", length: 2 }, + unwatchFile: { async: true, fn: "unwatchFile", length: 2 }, + unlink: { async: true, fn: "unlink", length: 2 }, + unlinkSync: { async: false, fn: "unlinkSync", length: 1 }, + utimes: { async: true, fn: "utimes", length: 4 }, + utimesSync: { async: false, fn: "utimesSync", length: 3 }, + watch: { async: true, fn: "watch", length: 3 }, + watchFile: { async: true, fn: "watchFile", length: 3 }, + writeFile: { async: true, fn: "writeFile", length: 4 }, + writeFileSync: { async: false, fn: "writeFileSync", length: 3 }, + write: { async: true, fn: "write", length: 6 }, + writeSync: { async: false, fn: "writeSync", length: 5 }, + writev: { async: true, fn: "writev", length: 4 }, + writevSync: { async: false, fn: "writevSync", length: 3 }, + realpathNative: { async: true, fn: "realpathNative", length: 3 }, + realpathNativeSync: { async: false, fn: "realpathNativeSync", length: 3 }, Dirent: { getter: "getDirent" }, Stats: { getter: "getStats" }, }, diff --git a/src/bun.js/webcore/response.classes.ts b/src/bun.js/webcore/response.classes.ts index 27c26d0be6..06cc53375d 100644 --- a/src/bun.js/webcore/response.classes.ts +++ b/src/bun.js/webcore/response.classes.ts @@ -13,13 +13,13 @@ export default [ overridesToJS: true, memoryCost: true, proto: { - text: { fn: "getText" }, - json: { fn: "getJSON" }, - bytes: { fn: "getBytes" }, + text: { fn: "getText", async: true }, + json: { fn: "getJSON", async: true }, + bytes: { fn: "getBytes", async: true }, body: { getter: "getBody", cache: true }, - arrayBuffer: { fn: "getArrayBuffer" }, - formData: { fn: "getFormData" }, - blob: { fn: "getBlob" }, + arrayBuffer: { fn: "getArrayBuffer", async: true }, + formData: { fn: "getFormData", async: true }, + blob: { fn: "getBlob", async: true }, clone: { fn: "doClone", length: 1 }, cache: { getter: "getCache", @@ -91,13 +91,14 @@ export default [ }, body: { getter: "getBody", cache: true }, - text: { fn: "getText" }, - json: { fn: "getJSON" }, - bytes: { fn: "getBytes" }, - arrayBuffer: { fn: "getArrayBuffer" }, - blob: { fn: "getBlob" }, + text: { fn: "getText", async: true }, + json: { fn: "getJSON", async: true }, + bytes: { fn: "getBytes", async: true }, + arrayBuffer: { fn: "getArrayBuffer", async: true }, + blob: { fn: "getBlob", async: true }, + formData: { fn: "getFormData", async: true }, + clone: { fn: "doClone", length: 1 }, - formData: { fn: "getFormData" }, type: { getter: "getResponseType", @@ -137,16 +138,16 @@ export default [ values: ["stream"], overridesToJS: true, proto: { - text: { fn: "getText" }, - json: { fn: "getJSON" }, - arrayBuffer: { fn: "getArrayBuffer" }, + text: { fn: "getText", async: true }, + json: { fn: "getJSON", async: true }, + arrayBuffer: { fn: "getArrayBuffer", async: true }, slice: { fn: "getSlice", length: 2 }, stream: { fn: "getStream", length: 1 }, - formData: { fn: "getFormData" }, + formData: { fn: "getFormData", async: true }, exists: { fn: "getExists", length: 0 }, // Non-standard, but consistent! - bytes: { fn: "getBytes" }, + bytes: { fn: "getBytes", async: true }, type: { getter: "getType", diff --git a/src/codegen/bundle-modules.ts b/src/codegen/bundle-modules.ts index 037087bf15..7719a8c36d 100644 --- a/src/codegen/bundle-modules.ts +++ b/src/codegen/bundle-modules.ts @@ -106,9 +106,12 @@ for (let i = 0; i < nativeStartIndex; i++) { isBuiltin = false; } if (isBuiltin) { - throw new Error( - `Cannot use ESM import statement within builtin modules. Use require("${imp.path}") instead. See src/js/README.md`, + const err = new Error( + `Cannot use ESM import statement within builtin modules. Use require("${imp.path}") instead. See src/js/README.md (from ${moduleList[i]})`, ); + err.name = "BunError"; + err.fileName = moduleList[i]; + throw err; } } } diff --git a/src/codegen/class-definitions.ts b/src/codegen/class-definitions.ts index 5ce2549620..3893d6877b 100644 --- a/src/codegen/class-definitions.ts +++ b/src/codegen/class-definitions.ts @@ -44,6 +44,13 @@ export type Field = } & PropertyAttribute) | ({ fn: string; + + /** + * Mark it as an async function in the TypeScript definition. + * + * Does not do anything at runtime. + */ + async?: boolean; /** * Number of parameters accepted by the function. * @@ -94,7 +101,7 @@ export class ClassDefinition { /** * ## IMPORTANT * You _must_ free the pointer to your native class! - * + * * Example for pointers only owned by JavaScript classes: * ```zig * pub const NativeClass = struct { @@ -125,7 +132,7 @@ export class ClassDefinition { * // ... * }); * } - * + * * fn deinit(this: *NativeClass) void { * // free allocations owned by this class, then free the struct itself. * bun.destroy(this); diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 4626a53f27..ee7e7570c0 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -2636,4 +2636,235 @@ if (!process.env.ONLY_ZIG) { `${outBase}/ZigGeneratedClasses+lazyStructureImpl.h`, initLazyClasses(classes.map(a => generateLazyClassStructureImpl(a.name, a))) + "\n" + visitLazyClasses(classes), ); + + await writeIfNotChanged(`${outBase}/ZigGeneratedClasses.d.ts`, [generateBuiltinTypes(classes)]); +} + +/** + * Generates a basic TypeScript type signature string and corresponding Zig source comment + * for a given property definition. + * Returns null if the property should not be included in the types (e.g., private). + */ +function getPropertySignatureWithComment( + propName: string, + propDef: Field, + classDef: ClassDefinition, +): { signature: string; comment: string | null } | null { + let tsPropName = propName; + // Handle well-known symbols + if (tsPropName.startsWith("@@")) { + tsPropName = `[Symbol.${tsPropName.slice(2)}]`; + } else if (/[^a-zA-Z0-9_$]/.test(tsPropName)) { + // Quote property names that are not valid JS identifiers (e.g., contain '-') + tsPropName = `"${tsPropName}"`; + } + + if ("privateSymbol" in propDef) { + tsPropName = `$${propDef.privateSymbol}`; + } + + // --- Skip internal/private properties --- + if ("internal" in propDef) { + return null; + } + + // --- Determine Type and Readonly Status --- + let signature = ""; + let isMethod = false; + let isReadOnly = false; + let commentLines: string[] = []; + + if ("fn" in propDef || "builtin" in propDef) { + const length = propDef.length ?? 0; + let args = Array(length) + .fill(0) + .map((_, i) => `arg${i}?: unknown`) + .concat(...(length > 0 ? ["...args: unknown[]"] : [])) + .join(", "); + let returnType = "unknown"; + if (propDef.async) { + returnType = "Promise"; + } + + signature = `${tsPropName}(${args}): ${returnType};`; // Basic method signature + isMethod = true; + if ("fn" in propDef) { + commentLines.push( + ` Look for a function like this: + * \`\`\`zig + * fn ${propDef.fn}(this: *${classDef.name}, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { ... } + * \`\`\``, + ); + } else if ("builtin" in propDef) { + commentLines.push(`* C++ builtin name: \`${propDef.builtin}\``); + } + } else if ("accessor" in propDef) { + signature = `${tsPropName}: unknown;`; // Read-write accessor + commentLines.push(` zig ⚡ \`${propDef.accessor.getter}\``); + commentLines.push( + ` Look for a getter like this: + * \`\`\`zig + * fn ${propDef.accessor.getter}(this: *${classDef.name}, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { ... } + * \`\`\``, + ); + commentLines.push( + ` Look for a setter like this: + * \`\`\`zig + * fn ${propDef.accessor.setter}(this: *${classDef.name}, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError!void + * \`\`\``, + ); + if (propDef.cache) { + commentLines.push(` Cached value ${typeof propDef.cache === "string" ? `via m_${propDef.cache}` : ""}`); + } + } else if ("getter" in propDef) { + signature = `${tsPropName}: unknown;`; // Getter, possibly with setter + isReadOnly = !propDef.writable; // Mark readonly if only getter or explicitly not writable + commentLines.push( + ` Look for a getter like this: + * \`\`\`zig + * fn ${propDef.getter}(this: *${classDef.name}, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { ... } + * \`\`\``, + ); + if (propDef.writable) { + commentLines.push(` Writable`); // Implicitly means a setter exists or is generated + } + } else if ("setter" in propDef) { + // Can't represent pure write-only in interfaces easily, treat as read-write + signature = `${tsPropName}: unknown;`; + commentLines.push( + ` Look for a setter like this: + * \`\`\`zig + * fn ${propDef.setter}(this: *${classDef.name}, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError!void { ... } + * \`\`\``, + ); + } else { + // Unknown property type or skipped type (like internal) + return null; + } + + // --- Add Modifiers --- + if (isReadOnly && !isMethod) { + signature = `readonly ${signature}`; + } + // --- Format Comment --- + const comment = commentLines.length > 0 ? `/**\n *${commentLines.join("\n *")}\n */` : null; + + return { signature, comment }; +} + +/** + * Generates TypeScript type definitions (interfaces) for all provided class definitions. + * Creates content for a single ambient declaration file (ZigGeneratedClasses.d.ts). + */ +export function generateBuiltinTypes(classes: ClassDefinition[]): string { + const typeDeclarations: string[] = []; + + for (const classDef of classes) { + // Skip classes marked as zigOnly, as they shouldn't have JS/TS counterparts + if ((classDef as any).zigOnly) continue; + + const instanceMembers: string[] = []; + const staticMembers: string[] = []; + const constructorInterfaceName = `${classDef.name}Constructor`; + const staticsInterfaceName = `${classDef.name}Statics`; + + // --- Process Instance Members (proto, own, values) --- + for (const [propName, propDef] of Object.entries(classDef.proto || {})) { + const result = getPropertySignatureWithComment(propName, propDef, classDef); + if (result) { + if (result.comment) instanceMembers.push(` ${result.comment}`); + instanceMembers.push(` ${result.signature}`); + } + } + + for (const [propName, zigFieldName] of Object.entries(classDef.own || {})) { + instanceMembers.push(` readonly ${propName}: any;`); + } + + // --- Process Static Members (klass) --- + for (const [propName, propDef] of Object.entries(classDef.klass || {})) { + const result = getPropertySignatureWithComment(propName, propDef, classDef); + if (result) { + if (result.comment) staticMembers.push(` ${result.comment}`); + staticMembers.push(` ${result.signature}`); + } + } + + // --- Generate Instance Interface --- + typeDeclarations.push(` interface ${classDef.name} {`); + if (instanceMembers.length === 0) { + typeDeclarations.push(` /* Opaque interface */`); + } else { + typeDeclarations.push(...instanceMembers); + } + typeDeclarations.push(` }`); + typeDeclarations.push(""); // Blank line separator + + // --- Determine if Constructor/Static Interface is needed --- + const hasStaticMembers = staticMembers.length > 0; + const isConstructible = !!classDef.construct; + const isCallable = !!classDef.call; + const hasExplicitConstructor = !classDef.noConstructor; + + const needsConstructorInterface = isConstructible || isCallable || (hasStaticMembers && hasExplicitConstructor); + const needsStaticInterface = hasStaticMembers && !hasExplicitConstructor && !isConstructible && !isCallable; + const needsGlobalVar = hasExplicitConstructor || needsStaticInterface; + + // --- Generate Constructor Interface (if applicable) --- + if (needsConstructorInterface) { + typeDeclarations.push(` interface ${constructorInterfaceName} {`); + if (isConstructible) { + typeDeclarations.push(` new(...args: any[]): ${classDef.name};`); + typeDeclarations.push(` prototype: ${classDef.name};`); + } + if (isCallable) { + // Add call signature if the constructor itself is callable + typeDeclarations.push(` (...args: any[]): any;`); + } + + // Add static members + if (staticMembers.length > 0) { + typeDeclarations.push(`\n // Static members`); + typeDeclarations.push(...staticMembers); + } + typeDeclarations.push(` }`); + typeDeclarations.push(""); // Blank line separator + } + + // --- Generate Statics Interface (if applicable, for noConstructor classes with statics) --- + if (needsStaticInterface) { + typeDeclarations.push(` interface ${staticsInterfaceName} {`); + if (staticMembers.length > 0) { + typeDeclarations.push(`\n // Static members`); + typeDeclarations.push(...staticMembers); + } + typeDeclarations.push(` }`); + typeDeclarations.push(""); // Blank line separator + } + + // --- Generate Global Variable Declaration --- + if (needsGlobalVar) { + const interfaceToUse = needsConstructorInterface ? constructorInterfaceName : staticsInterfaceName; + // Declare the global variable holding the constructor or static methods/props + typeDeclarations.push(` var ${classDef.name}: ${interfaceToUse};`); + typeDeclarations.push(""); // Blank line separator + } + } // End loop through classes + + // --- Assemble Final File Content --- + return `// GENERATED CODE - DO NOT MODIFY BY HAND +// Generated by generate-classes.ts + + +/** + * Type definitions for Bun's built-in classes implemented in Zig. + * Do not edit this file directly. + * @generated + * + * This namespace does not exist at runtime! + */ +declare namespace $ZigGeneratedClasses { +${typeDeclarations.map(line => (line ? " " + line : "")).join("\n")} +} +`; } diff --git a/src/codegen/generate-node-errors.ts b/src/codegen/generate-node-errors.ts index 0d402d535f..833827273c 100644 --- a/src/codegen/generate-node-errors.ts +++ b/src/codegen/generate-node-errors.ts @@ -1,5 +1,6 @@ import path from "node:path"; import NodeErrors from "../bun.js/bindings/ErrorCode.ts"; +import { writeIfNotChanged } from "./helpers.ts"; const outputDir = process.argv[2]; if (!outputDir) { @@ -91,7 +92,7 @@ for (let [code, constructor, name, ...other_constructors] of NodeErrors) { if (name == null) name = constructor.name; // it's useful to avoid the prefix, but module not found has a prefixed and unprefixed version - const codeWithoutPrefix = code === 'ERR_MODULE_NOT_FOUND' ? code : code.replace(/^ERR_/, ''); + const codeWithoutPrefix = code === "ERR_MODULE_NOT_FOUND" ? code : code.replace(/^ERR_/, ""); enumHeader += ` ${code} = ${i},\n`; listHeader += ` { JSC::ErrorType::${constructor.name}, "${name}"_s, "${code}"_s },\n`; @@ -148,6 +149,35 @@ zig += ` }; `; -await Bun.write(path.join(outputDir, "ErrorCode+List.h"), enumHeader); -await Bun.write(path.join(outputDir, "ErrorCode+Data.h"), listHeader); -await Bun.write(path.join(outputDir, "ErrorCode.zig"), zig); +let builtindtsPath = path.join(import.meta.dir, "..", "..", "src", "js", "builtins.d.ts"); +let builtindts = await Bun.file(builtindtsPath).text(); + +let dts = ` +// Generated by: src/codegen/generate-node-errors.ts +// Input: src/bun.js/bindings/ErrorCode.ts + +// Global error code functions for TypeScript +`; +for (const [code, constructor, name, ...other_constructors] of NodeErrors) { + const hasExistingOverride = builtindts.includes(`declare function $${code}`); + if (hasExistingOverride) { + continue; + } + + const namedError = + name && name !== constructor.name + ? `${constructor.name} & { name: "${name}", code: "${code}" }` + : `${constructor.name} & { code: "${code}" }`; + dts += ` +/** + * Construct an {@link ${constructor.name} ${constructor.name}} with the \`"${code}"\` error code. + * + * To override this, update ErrorCode.cpp. To remove this generated type, mention \`"${code}"\` in builtins.d.ts. + */ +declare function $${code}(message: string): ${namedError};\n`; +} + +writeIfNotChanged(path.join(outputDir, "ErrorCode+List.h"), enumHeader); +writeIfNotChanged(path.join(outputDir, "ErrorCode+Data.h"), listHeader); +writeIfNotChanged(path.join(outputDir, "ErrorCode.zig"), zig); +writeIfNotChanged(path.join(outputDir, "ErrorCode.d.ts"), dts); diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts index cc1f8dfc1e..a692f11793 100644 --- a/src/js/builtins.d.ts +++ b/src/js/builtins.d.ts @@ -1,4 +1,8 @@ /// +/// +/// +/// + // Typedefs for JSC intrinsics. Instead of @, we use $ type TODO = any; @@ -50,6 +54,50 @@ declare var $sloppy; declare var $alwaysInline; declare function $extractHighWaterMarkFromQueuingStrategyInit(obj: any): any; +/** + * Overrides ** + */ + +interface ReadableStreamDefaultController extends _ReadableStreamDefaultController { + $controlledReadableStream: ReadableStream; + $underlyingSource: UnderlyingSource; + $queue: any; + $started: number; + $closeRequested: boolean; + $pullAgain: boolean; + $pulling: boolean; + $strategy: any; + + $pullAlgorithm(): void; + $pull: typeof ReadableStreamDefaultController.prototype.pull; + $cancel: typeof ReadableStreamDefaultController.prototype.cancel; + $cancelAlgorithm: (reason?: any) => void; + $close: typeof ReadableStreamDefaultController.prototype.close; + $enqueue: typeof ReadableStreamDefaultController.prototype.enqueue; + $error: typeof ReadableStreamDefaultController.prototype.error; +} + +declare var ReadableStreamDefaultController: { + prototype: ReadableStreamDefaultController; + new (): ReadableStreamDefaultController; +}; + +interface ReadableStream extends _ReadableStream { + $highWaterMark: number; + $bunNativePtr: undefined | TODO; + $asyncContext?: {}; + $disturbed: boolean; + $state: $streamClosed | $streamErrored | $streamReadable | $streamWritable | $streamClosedAndErrored; +} + +declare var ReadableStream: { + prototype: ReadableStream; + new (): ReadableStream; +}; + +interface Console { + $writer: ReturnType; +} // JSC defines their intrinsics in a nice list here: // https://github.com/WebKit/WebKit/blob/main/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h @@ -63,14 +111,7 @@ declare function $argument(index: number): any | undefined; declare function $argumentCount(): number; /** array.push(item) */ declare function $arrayPush(array: T[], item: T): void; -/** gets a property on an object */ -declare function $getByIdDirect(obj: any, key: string): T; -/** - * gets a private property on an object. translates to the `op_get_by_id_direct` bytecode. - * - * TODO: clarify what private means exactly. - */ -declare function $getByIdDirectPrivate(obj: any, key: string): T; + /** * gets a property on an object */ @@ -128,7 +169,6 @@ declare function $isProxyObject(obj: unknown): obj is Proxy; declare function $isDerivedArray(): TODO; declare function $isGenerator(obj: unknown): obj is Generator; declare function $isAsyncGenerator(obj: unknown): obj is AsyncGenerator; -declare function $isPromise(obj: unknown): obj is Promise; declare function $isRegExpObject(obj: unknown): obj is RegExp; declare function $isMap(obj: unknown): obj is Map; declare function $isSet(obj: unknown): obj is Set; @@ -157,7 +197,21 @@ declare function $throwOutOfMemoryError(): never; declare function $tryGetById(): TODO; declare function $tryGetByIdWithWellKnownSymbol(obj: any, key: WellKnownSymbol): any; declare function $putByIdDirect(obj: any, key: PropertyKey, value: any): void; -declare function $putByIdDirectPrivate(obj: any, key: PropertyKey, value: any): void; + +/** + * Sets a private property on an object. + * Translates to the `op_put_by_id_direct` bytecode. + * + * @param obj The object to set the private property on + * @param key The key of the private property (without the "$" prefix) + * @param value The value to set the private property to + */ +declare function $putByIdDirectPrivate, K extends string>( + obj: T, + key: K, + value: T[`$${K}`], +): void; + declare function $putByValDirect(obj: any, key: PropertyKey, value: any): void; declare function $putByValWithThisSloppy(): TODO; declare function $putByValWithThisStrict(): TODO; @@ -368,7 +422,7 @@ declare function $isDisturbed(): TODO; declare function $isPaused(): TODO; declare function $join(): TODO; declare function $kind(): TODO; -declare function $lazyStreamPrototypeMap(): TODO; +declare const $lazyStreamPrototypeMap: Map; declare function $loadModule(): TODO; declare function $localStreams(): TODO; declare function $main(): TODO; @@ -425,7 +479,13 @@ declare function $requireESM(path: string): any; declare const $requireMap: Map; declare const $internalModuleRegistry: InternalFieldObject; declare function $resolve(name: string, from: string): Promise; -declare function $resolveSync(name: string, from: string, isESM?: boolean, isUserRequireResolve?: boolean, paths?: string[]): string; +declare function $resolveSync( + name: string, + from: string, + isESM?: boolean, + isUserRequireResolve?: boolean, + paths?: string[], +): string; declare function $resume(): TODO; declare function $search(): TODO; declare function $searchParams(): TODO; @@ -534,6 +594,7 @@ declare interface UnderlyingSource { $lazy?: boolean; $bunNativePtr?: undefined | TODO; autoAllocateChunkSize?: number; + $stream?: ReadableStream; } declare class OutOfMemoryError { @@ -724,3 +785,49 @@ declare function $toClass(fn: Function, name: string, base?: Function | undefine declare function $min(a: number, b: number): number; declare function $checkBufferRead(buf: Buffer, offset: number, byteLength: number): undefined; + +/** + * Schedules a callback to be invoked as a microtask. + */ +declare function $enqueueJob any>(callback: T, ...args: Parameters): void; + +declare function $rejectPromise(promise: Promise, reason: unknown): void; +declare function $resolvePromise(promise: Promise, value: unknown): void; + +interface Map { + $get: typeof Map.prototype.get; + $set: typeof Map.prototype.set; +} + +interface ObjectConstructor { + $defineProperty: typeof Object.defineProperty; + $defineProperties: typeof Object.defineProperties; +} + +declare const $Object: ObjectConstructor; + +/** gets a property on an object */ +declare function $getByIdDirect(obj: any, key: string): T; + +/** + * Gets a private property on an object. + * Translates to the `op_get_by_id_direct` bytecode. + * + * @param obj The object to get the private property from + * @param key The key of the private property (without the "$" prefix) + * @returns The value of the private property + */ +declare function $getByIdDirectPrivate( + obj: T, + key: K, +): K extends keyof T ? T[`$${K}`] : T extends { [P in `$${K}`]: infer V } ? V : never; + +declare var $Promise: PromiseConstructor; + +declare function $isPromise(value: unknown): value is Promise; + +declare type $ReadableStream = ReadableStream; +declare type $ReadableStreamBYOBReader = ReadableStreamBYOBReader; +declare type $ReadableStreamDefaultReader = ReadableStreamDefaultReader; +declare type $ReadableStreamDefaultController = ReadableStreamDefaultController; +declare type $ReadableStreamDirectController = ReadableStreamDirectController; diff --git a/src/js/builtins/BundlerPlugin.ts b/src/js/builtins/BundlerPlugin.ts index 7d9ba852d4..ed427a39a7 100644 --- a/src/js/builtins/BundlerPlugin.ts +++ b/src/js/builtins/BundlerPlugin.ts @@ -20,6 +20,9 @@ interface BundlerPlugin { addFilter(filter, namespace, number): void; generateDeferPromise(id: number): Promise; promises: Array> | undefined; + + onBeforeParse: (filter: RegExp, namespace: string, addon: unknown, symbol: string, external?: unknown) => void; + $napiDlopenHandle: number; } // Extra types @@ -42,8 +45,6 @@ interface PluginBuilderExt extends PluginBuilder { esbuild: any; } -type BeforeOnParseExternal = unknown; - /** * Used by Bun.serve() to resolve and load plugins. */ @@ -223,8 +224,7 @@ export function runSetupFunction( const processSetupResult = () => { var anyOnLoad = false, - anyOnResolve = false, - anyOnBeforeParse = false; + anyOnResolve = false; for (let [namespace, callbacks] of onLoadPlugins.entries()) { for (var [filter] of callbacks) { @@ -243,7 +243,6 @@ export function runSetupFunction( for (let [namespace, callbacks] of onBeforeParsePlugins.entries()) { for (let [filter, addon, symbol, external] of callbacks) { this.onBeforeParse(filter, namespace, addon, symbol, external); - anyOnBeforeParse = true; } } diff --git a/src/js/builtins/CommonJS.ts b/src/js/builtins/CommonJS.ts index 98a6cec895..4fe14e23eb 100644 --- a/src/js/builtins/CommonJS.ts +++ b/src/js/builtins/CommonJS.ts @@ -17,7 +17,7 @@ $overriddenName = "require"; $visibility = "Private"; export function overridableRequire(this: JSCommonJSModule, originalId: string, options: { paths?: string[] } = {}) { const id = $resolveSync(originalId, this.filename, false, false, options ? options.paths : undefined); - if (id.startsWith('node:')) { + if (id.startsWith("node:")) { if (id !== originalId) { // A terrible special case where Node.js allows non-prefixed built-ins to // read the require cache. Though they never write to it, which is so silly. @@ -30,7 +30,7 @@ export function overridableRequire(this: JSCommonJSModule, originalId: string, o return existing.exports; } } - + return this.$requireNativeModule(id); } else { const existing = $requireMap.$get(id); @@ -73,6 +73,8 @@ export function overridableRequire(this: JSCommonJSModule, originalId: string, o const mod = $createCommonJSModule(id, {}, false, this); $requireMap.$set(id, mod); + var out: LoaderModule | -1; + // This is where we load the module. We will see if Module._load and // Module._compile are actually important for compatibility. // @@ -82,7 +84,7 @@ export function overridableRequire(this: JSCommonJSModule, originalId: string, o if (IS_BUN_DEVELOPMENT) { $assert(mod.id === id); try { - var out = this.$require( + out = this.$require( id, mod, // did they pass a { type } object? @@ -96,12 +98,7 @@ export function overridableRequire(this: JSCommonJSModule, originalId: string, o throw E; } } else { - var out = this.$require( - id, - mod, - $argumentCount(), - $argument(1), - ); + out = this.$require(id, mod, $argumentCount(), $argument(1)); } // -1 means we need to lookup the module from the ESM registry. @@ -146,8 +143,18 @@ export function overridableRequire(this: JSCommonJSModule, originalId: string, o } $visibility = "Private"; -export function requireResolve(this: string | { filename?: string; id?: string }, id: string, options: { paths?: string[] } = {}) { - return $resolveSync(id, typeof this === "string" ? this : this?.filename ?? this?.id ?? "", false, true, options ? options.paths : undefined); +export function requireResolve( + this: string | { filename?: string; id?: string }, + id: string, + options: { paths?: string[] } = {}, +) { + return $resolveSync( + id, + typeof this === "string" ? this : (this?.filename ?? this?.id ?? ""), + false, + true, + options ? options.paths : undefined, + ); } $visibility = "Private"; @@ -161,7 +168,6 @@ export function internalRequire(id: string, parent: JSCommonJSModule) { return module.exports; } - $visibility = "Private"; export function loadEsmIntoCjs(resolvedSpecifier: string) { var loader = Loader; @@ -346,7 +352,7 @@ export function createRequireCache() { }, }; var proxy = new Proxy(inner, { - get(target, key: string) { + get(_target, key: string) { const entry = $requireMap.$get(key); if (entry) return entry; @@ -360,23 +366,23 @@ export function createRequireCache() { return inner[key]; }, - set(target, key: string, value) { + set(_target, key: string, value) { $requireMap.$set(key, value); return true; }, - has(target, key: string) { + has(_target, key: string) { return $requireMap.$has(key) || Boolean(Loader.registry.$get(key)?.evaluated); }, - deleteProperty(target, key: string) { + deleteProperty(_target, key: string) { moduleMap.$delete(key); $requireMap.$delete(key); Loader.registry.$delete(key); return true; }, - ownKeys(target) { + ownKeys(_target) { var array = [...$requireMap.$keys()]; for (const key of Loader.registry.$keys()) { if (!array.includes(key) && Loader.registry.$get(key)?.evaluated) { @@ -387,11 +393,11 @@ export function createRequireCache() { }, // In Node, require.cache has a null prototype - getPrototypeOf(target) { + getPrototypeOf(_target) { return null; }, - getOwnPropertyDescriptor(target, key: string) { + getOwnPropertyDescriptor(_target, key: string) { if ($requireMap.$has(key) || Loader.registry.$get(key)?.evaluated) { return { configurable: true, @@ -408,18 +414,18 @@ type WrapperMutate = (start: string, end: string) => void; export function getWrapperArrayProxy(onMutate: WrapperMutate) { const wrapper = ["(function(exports,require,module,__filename,__dirname){", "})"]; return new Proxy(wrapper, { - set(target, prop, value, receiver) { - Reflect.set(target, prop, value, receiver); + set(_target, prop, value, receiver) { + Reflect.set(wrapper, prop, value, receiver); onMutate(wrapper[0], wrapper[1]); return true; }, - defineProperty(target, prop, descriptor) { - Reflect.defineProperty(target, prop, descriptor); + defineProperty(_target, prop, descriptor) { + Reflect.defineProperty(wrapper, prop, descriptor); onMutate(wrapper[0], wrapper[1]); return true; }, - deleteProperty(target, prop) { - Reflect.deleteProperty(target, prop); + deleteProperty(_target, prop) { + Reflect.deleteProperty(wrapper, prop); onMutate(wrapper[0], wrapper[1]); return true; }, diff --git a/src/js/builtins/ConsoleObject.ts b/src/js/builtins/ConsoleObject.ts index 7377e5710c..312b280923 100644 --- a/src/js/builtins/ConsoleObject.ts +++ b/src/js/builtins/ConsoleObject.ts @@ -15,7 +15,7 @@ export function asyncIterator(this: Console) { async function* ConsoleAsyncIterator() { var reader = stream.getReader(); - var deferredError; + var deferredError: Error | undefined; try { if (i !== -1) { last = i + 1; @@ -99,13 +99,14 @@ export function asyncIterator(this: Console) { actualChunk = undefined!; } } catch (e) { - deferredError = e; + deferredError = e as Error; } finally { reader.releaseLock(); + } - if (deferredError) { - throw deferredError; - } + if (deferredError) { + // eslint-disable-next-line no-throw-literal + throw deferredError; } } @@ -155,7 +156,6 @@ export function createConsoleConstructor(console: typeof globalThis.console) { const StringPrototypeSplit = String.prototype.split; const NumberPrototypeToFixed = Number.prototype.toFixed; const StringPrototypeNormalize = String.prototype.normalize; - const StringPrototypeCodePointAt = String.prototype.codePointAt; const ArrayPrototypeMap = Array.prototype.map; const ArrayPrototypeJoin = Array.prototype.join; const ArrayPrototypePush = Array.prototype.push; diff --git a/src/js/builtins/EventSource.ts b/src/js/builtins/EventSource.ts deleted file mode 100644 index 5a65643237..0000000000 --- a/src/js/builtins/EventSource.ts +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright 2023 Codeblog Corp. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -export function getEventSource() { - type Socket = Awaited>>; - - class EventSource extends EventTarget { - #url; - #state; - #onerror; - #onmessage; - #onopen; - #is_tls = false; - #socket: Socket | null = null; - #data_buffer = ""; - #send_buffer = ""; - #lastEventID = ""; - #reconnect = true; - #content_length = 0; // 0 means chunked -1 means not informed aka no auto end - #received_length = 0; - #reconnection_time = 0; - #reconnection_timer: Timer | null = null; - - static #ConnectNextTick(self: EventSource) { - self.#connect(); - } - static #SendRequest(socket: Socket, url: URL) { - const self = socket.data; - const last_event_header = self.#lastEventID ? `Last-Event-ID: ${self.#lastEventID}\r\n` : ""; - const request = `GET ${url.pathname}${url.search} HTTP/1.1\r\nHost: bun\r\nContent-type: text/event-stream\r\nContent-length: 0\r\n${last_event_header}\r\n`; - const sended = socket.write(request); - if (sended !== request.length) { - self.#send_buffer = request.substring(sended); - } - } - - static #ProcessChunk(self: EventSource, chunks: string, offset: number) { - for (;;) { - if (offset >= chunks.length) { - return; - } - let chunk_end_idx = -1; - let start_idx = chunks.indexOf("\r\n", offset); - const chunk_start_idx = start_idx + 2; - if (start_idx > 0) { - if (self.#content_length === 0) { - const chunk_size = parseInt(chunks.substring(offset, start_idx), 16); - if (chunk_size === 0) { - // no more chunks - self.#state = 2; - self.#socket?.end(); - return; - } - chunk_end_idx = chunk_start_idx + chunk_size; - } else { - //not chunked - chunk_end_idx = chunks.length; - } - } else { - // wait for the chunk if is chunked - if (self.#data_buffer.length === 0) { - self.#data_buffer += chunks.substring(offset); - return; - } - chunk_end_idx = chunks.length; - } - - // check for chunk end - let chunk = chunks.substring(chunk_start_idx, chunk_end_idx); - offset = chunk_end_idx + 2; - let chunk_offset = 0; - // wait for data end - let event_idx = chunk.indexOf("\n\n"); - if (event_idx == -1) { - // wait for more data - self.#data_buffer += chunks.substring(chunk_start_idx); - return; - } - - // combine data - if (self.#data_buffer.length) { - self.#data_buffer += chunk; - chunk = self.#data_buffer; - self.#data_buffer = ""; - } - - let more_events = true; - while (more_events) { - const event_data = chunk.substring(chunk_offset, event_idx); - - let type; - let data = ""; - let id; - let event_line_idx = 0; - let retry = -1; - for (;;) { - let idx = event_data.indexOf("\n", event_line_idx); - if (idx === -1) { - if (event_line_idx >= event_data.length) { - break; - } - idx = event_data.length; - } - const line = event_data.substring(event_line_idx, idx); - if (line.startsWith("data:")) { - if (data.length) { - data += `\n${line.substring(5).trim()}`; - } else { - data = line.substring(5).trim(); - } - } else if (line.startsWith("event:")) { - type = line.substring(6).trim(); - } else if (line.startsWith("id:")) { - id = line.substring(3).trim(); - } else if (line.startsWith("retry:")) { - retry = parseInt(line.substring(6).trim(), 10); - if (retry !== retry) { - retry = -1; - } - } - event_line_idx = idx + 1; - } - self.#lastEventID = id || ""; - if (retry >= 0) { - self.#reconnection_time = retry; - } - - if (data || id || type) { - self.dispatchEvent( - new MessageEvent(type || "message", { - data: data || "", - origin: self.#url.origin, - // @ts-ignore - source: self, - lastEventId: id, - }), - ); - } - - // no more events - if (chunk.length === event_idx + 2) { - more_events = false; - break; - } - - const next_event_idx = chunk.indexOf("\n\n", event_idx + 1); - if (next_event_idx === -1) { - break; - } - chunk_offset = event_idx; - event_idx = next_event_idx; - } - } - } - static #Handlers = { - open(socket: Socket) { - const self = socket.data; - self.#socket = socket; - if (!self.#is_tls) { - EventSource.#SendRequest(socket, self.#url); - } - }, - handshake(socket: Socket, success: boolean, verifyError: Error) { - const self = socket.data; - if (success) { - EventSource.#SendRequest(socket, self.#url); - } else { - self.#state = 2; - self.dispatchEvent(new ErrorEvent("error", { error: verifyError })); - socket.end(); - } - }, - data(socket: Socket, buffer: Buffer) { - const self = socket.data; - switch (self.#state) { - case 0: { - let text = buffer.toString(); - const headers_idx = text.indexOf("\r\n\r\n"); - if (headers_idx === -1) { - // wait headers - self.#data_buffer += text; - return; - } - - if (self.#data_buffer.length) { - self.#data_buffer += text; - text = self.#data_buffer; - self.#data_buffer = ""; - } - const headers = text.substring(0, headers_idx); - const status_idx = headers.indexOf("\r\n"); - - if (status_idx === -1) { - self.#state = 2; - self.dispatchEvent(new ErrorEvent("error", { error: new Error("Invalid HTTP request") })); - socket.end(); - return; - } - const status = headers.substring(0, status_idx); - if (status !== "HTTP/1.1 200 OK") { - self.#state = 2; - self.dispatchEvent(new ErrorEvent("error", { error: new Error(status) })); - socket.end(); - return; - } - - let start_idx = status_idx + 1; - let mime_type_ok = false; - let content_length = -1; - for (;;) { - let header_idx = headers.indexOf("\r\n", start_idx); - // No text/event-stream mime type - if (header_idx === -1) { - if (start_idx >= headers.length) { - if (!mime_type_ok) { - self.#state = 2; - self.dispatchEvent( - new ErrorEvent("error", { - error: new Error( - `EventSource's response has no MIME type and "text/event-stream" is required. Aborting the connection.`, - ), - }), - ); - socket.end(); - } - return; - } - - header_idx = headers.length; - } - - const header = headers.substring(start_idx + 1, header_idx); - const header_name_idx = header.indexOf(":"); - const header_name = header.substring(0, header_name_idx); - const is_content_type = - header_name.localeCompare("content-type", undefined, { sensitivity: "accent" }) === 0; - start_idx = header_idx + 1; - - if (is_content_type) { - if (header.endsWith(" text/event-stream")) { - mime_type_ok = true; - } else { - // wrong mime type - self.#state = 2; - self.dispatchEvent( - new ErrorEvent("error", { - error: new Error( - `EventSource's response has a MIME type that is not "text/event-stream". Aborting the connection.`, - ), - }), - ); - socket.end(); - return; - } - } else { - const is_content_length = - header_name.localeCompare("content-length", undefined, { sensitivity: "accent" }) === 0; - if (is_content_length) { - content_length = parseInt(header.substring(header_name_idx + 1).trim(), 10); - if (content_length !== content_length || content_length <= 0) { - self.dispatchEvent( - new ErrorEvent("error", { - error: new Error(`EventSource's Content-Length is invalid. Aborting the connection.`), - }), - ); - socket.end(); - return; - } - if (mime_type_ok) { - break; - } - } else { - const is_transfer_encoding = - header_name.localeCompare("transfer-encoding", undefined, { sensitivity: "accent" }) === 0; - if (is_transfer_encoding) { - if (header.substring(header_name_idx + 1).trim() !== "chunked") { - self.dispatchEvent( - new ErrorEvent("error", { - error: new Error(`EventSource's Transfer-Encoding is invalid. Aborting the connection.`), - }), - ); - socket.end(); - return; - } - content_length = 0; - if (mime_type_ok) { - break; - } - } - } - } - } - - self.#content_length = content_length; - self.#state = 1; - self.dispatchEvent(new Event("open")); - const chunks = text.substring(headers_idx + 4); - EventSource.#ProcessChunk(self, chunks, 0); - if (self.#content_length > 0) { - self.#received_length += chunks.length; - if (self.#received_length >= self.#content_length) { - self.#state = 2; - socket.end(); - } - } - return; - } - case 1: - EventSource.#ProcessChunk(self, buffer.toString(), 2); - if (self.#content_length > 0) { - self.#received_length += buffer.byteLength; - if (self.#received_length >= self.#content_length) { - self.#state = 2; - socket.end(); - } - } - return; - default: - break; - } - }, - drain(socket: Socket) { - const self = socket.data; - if (self.#state === 0) { - const request = self.#data_buffer; - if (request.length) { - const sended = socket.write(request); - if (sended !== request.length) { - socket.data.#send_buffer = request.substring(sended); - } else { - socket.data.#send_buffer = ""; - } - } - } - }, - close: EventSource.#Close, - end(socket: Socket) { - EventSource.#Close(socket).dispatchEvent( - new ErrorEvent("error", { error: new Error("Connection closed by server") }), - ); - }, - timeout(socket: Socket) { - EventSource.#Close(socket).dispatchEvent(new ErrorEvent("error", { error: new Error("Timeout") })); - }, - binaryType: "buffer", - }; - - static #Close(socket: Socket) { - const self = socket.data; - self.#socket = null; - self.#received_length = 0; - self.#state = 2; - if (self.#reconnect) { - if (self.#reconnection_timer) { - clearTimeout(self.#reconnection_timer); - } - self.#reconnection_timer = setTimeout(EventSource.#ConnectNextTick, self.#reconnection_time, self); - } - return self; - } - constructor(url: string, options = undefined) { - super(); - const uri = new URL(url); - this.#is_tls = uri.protocol === "https:"; - this.#url = uri; - this.#state = 2; - process.nextTick(EventSource.#ConnectNextTick, this); - } - - // Not web standard - ref() { - this.#reconnection_timer?.ref(); - this.#socket?.ref(); - } - - // Not web standard - unref() { - this.#reconnection_timer?.unref(); - this.#socket?.unref(); - } - - #connect() { - if (this.#state !== 2) return; - const uri = this.#url; - const is_tls = this.#is_tls; - this.#state = 0; - //@ts-ignore - Bun.connect({ - data: this, - socket: EventSource.#Handlers, - hostname: uri.hostname, - port: parseInt(uri.port || (is_tls ? "443" : "80"), 10), - tls: is_tls - ? { - requestCert: true, - rejectUnauthorized: false, - } - : false, - }).catch(err => { - super.dispatchEvent(new ErrorEvent("error", { error: err })); - if (this.#reconnect) { - if (this.#reconnection_timer) { - this.#reconnection_timer.unref?.(); - } - - this.#reconnection_timer = setTimeout(EventSource.#ConnectNextTick, 1000, this); - } - }); - } - - get url() { - return this.#url.href; - } - - get readyState() { - return this.#state; - } - - close() { - this.#reconnect = false; - this.#state = 2; - this.#socket?.unref(); - this.#socket?.end(); - } - - get onopen() { - return this.#onopen; - } - get onerror() { - return this.#onerror; - } - get onmessage() { - return this.#onmessage; - } - - set onopen(cb) { - if (this.#onopen) { - super.removeEventListener("close", this.#onopen); - } - super.addEventListener("open", cb); - this.#onopen = cb; - } - - set onerror(cb) { - if (this.#onerror) { - super.removeEventListener("error", this.#onerror); - } - super.addEventListener("error", cb); - this.#onerror = cb; - } - - set onmessage(cb) { - if (this.#onmessage) { - super.removeEventListener("message", this.#onmessage); - } - super.addEventListener("message", cb); - this.#onmessage = cb; - } - } - - Object.defineProperty(EventSource.prototype, "CONNECTING", { - enumerable: true, - value: 0, - }); - - Object.defineProperty(EventSource.prototype, "OPEN", { - enumerable: true, - value: 1, - }); - - Object.defineProperty(EventSource.prototype, "CLOSED", { - enumerable: true, - value: 2, - }); - - return EventSource; -} diff --git a/src/js/builtins/NodeModuleObject.ts b/src/js/builtins/NodeModuleObject.ts index 8c47278608..7d38192378 100644 --- a/src/js/builtins/NodeModuleObject.ts +++ b/src/js/builtins/NodeModuleObject.ts @@ -7,21 +7,20 @@ export function _initPaths() { // process.execPath is $PREFIX/bin/node except on Windows where it is // $PREFIX\node.exe where $PREFIX is the root of the Node.js installation. const path = require("node:path"); - const prefixDir = process.platform === "win32" ? - path.resolve(process.execPath, '..') : - path.resolve(process.execPath, '..', '..'); + const prefixDir = + process.platform === "win32" ? path.resolve(process.execPath, "..") : path.resolve(process.execPath, "..", ".."); - const paths = [path.resolve(prefixDir, 'lib', 'node')]; + const paths = [path.resolve(prefixDir, "lib", "node")]; if (homeDir) { - paths.unshift(path.resolve(homeDir, '.node_libraries')); - paths.unshift(path.resolve(homeDir, '.node_modules')); + paths.unshift(path.resolve(homeDir, ".node_libraries")); + paths.unshift(path.resolve(homeDir, ".node_modules")); } if (nodePath) { paths.unshift(...nodePath.split(path.delimiter).filter(Boolean)); } - const M = require('node:module'); + const M = require("node:module"); M.globalPaths = paths; } diff --git a/src/js/builtins/ProcessObjectInternals.ts b/src/js/builtins/ProcessObjectInternals.ts index e203bc0bb8..cbb2de0c74 100644 --- a/src/js/builtins/ProcessObjectInternals.ts +++ b/src/js/builtins/ProcessObjectInternals.ts @@ -30,7 +30,7 @@ const enum BunProcessStdinFdType { socket = 2, } -export function getStdioWriteStream(fd, isTTY: boolean, fdType: BunProcessStdinFdType) { +export function getStdioWriteStream(fd, isTTY: boolean, _fdType: BunProcessStdinFdType) { $assert(typeof fd === "number", `Expected fd to be a number, got ${typeof fd}`); let stream; @@ -174,7 +174,7 @@ export function getStdinStream(fd, isTTY: boolean, fdType: BunProcessStdinFdType $debug("internalRead();"); try { $assert(reader); - const { done, value } = await reader.read(); + const { value } = await reader.read(); if (value) { stream.push(value); @@ -203,7 +203,7 @@ export function getStdinStream(fd, isTTY: boolean, fdType: BunProcessStdinFdType } } - function triggerRead(size) { + function triggerRead(_size) { $debug("_read();", reader); if (reader && !shouldUnref) { diff --git a/src/js/builtins/ReadableByteStreamController.ts b/src/js/builtins/ReadableByteStreamController.ts index 10cd75028e..df15266224 100644 --- a/src/js/builtins/ReadableByteStreamController.ts +++ b/src/js/builtins/ReadableByteStreamController.ts @@ -30,7 +30,7 @@ export function initializeReadableByteStreamController(this, stream, underlyingB return $privateInitializeReadableByteStreamController.$call(this, stream, underlyingByteSource, highWaterMark); } -export function enqueue(this, chunk) { +export function enqueue(this: ReadableByteStreamController, chunk: ArrayBufferView) { if (!$isReadableByteStreamController(this)) throw $ERR_INVALID_THIS("ReadableByteStreamController"); if ($getByIdDirectPrivate(this, "closeRequested")) @@ -44,7 +44,7 @@ export function enqueue(this, chunk) { return $readableByteStreamControllerEnqueue(this, chunk); } -export function error(this, error) { +export function error(this: ReadableByteStreamController, error: any) { if (!$isReadableByteStreamController(this)) throw $ERR_INVALID_THIS("ReadableByteStreamController"); if ($getByIdDirectPrivate($getByIdDirectPrivate(this, "controlledReadableStream"), "state") !== $streamReadable) @@ -53,7 +53,7 @@ export function error(this, error) { $readableByteStreamControllerError(this, error); } -export function close(this) { +export function close(this: ReadableByteStreamController) { if (!$isReadableByteStreamController(this)) throw $ERR_INVALID_THIS("ReadableByteStreamController"); if ($getByIdDirectPrivate(this, "closeRequested")) throw new TypeError("Close has already been requested"); diff --git a/src/js/builtins/ReadableByteStreamInternals.ts b/src/js/builtins/ReadableByteStreamInternals.ts index 5ec95087a3..9087833aca 100644 --- a/src/js/builtins/ReadableByteStreamInternals.ts +++ b/src/js/builtins/ReadableByteStreamInternals.ts @@ -366,12 +366,12 @@ export function readableByteStreamControllerRespondWithNewView(controller, view) let firstDescriptor: PullIntoDescriptor | undefined = $getByIdDirectPrivate(controller, "pendingPullIntos").peek(); - if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) + if (firstDescriptor!.byteOffset + firstDescriptor!.bytesFilled !== view.byteOffset) throw new RangeError("Invalid value for view.byteOffset"); - if (firstDescriptor.byteLength !== view.byteLength) throw new RangeError("Invalid value for view.byteLength"); + if (firstDescriptor!.byteLength !== view.byteLength) throw new RangeError("Invalid value for view.byteLength"); - firstDescriptor.buffer = view.buffer; + firstDescriptor!.buffer = view.buffer; $readableByteStreamControllerRespondInternal(controller, view.byteLength); } @@ -672,10 +672,7 @@ interface PullIntoDescriptor { * An {@link ArrayBuffer} */ buffer: ArrayBuffer; - /** - * A positive integer representing the initial byte length of {@link buffer} - */ - bufferByteLength: number; + /** * A nonnegative integer byte offset into the {@link buffer} where the * underlying byte source will start writing @@ -691,12 +688,7 @@ interface PullIntoDescriptor { * {@link buffer} so far */ bytesFilled: number; - /** - * A positive integer representing the minimum number of bytes that must be - * written into the {@link buffer} before the associated read() request may be - * fulfilled. By default, this equals the element size. - */ - minimumFill: number; + /** * A positive integer representing the number of bytes that can be written * into the {@link buffer} at a time, using views of the type described by the diff --git a/src/js/builtins/ReadableStreamInternals.ts b/src/js/builtins/ReadableStreamInternals.ts index fd43a2119a..eb78fc549a 100644 --- a/src/js/builtins/ReadableStreamInternals.ts +++ b/src/js/builtins/ReadableStreamInternals.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (C) 2015 Canon Inc. All rights reserved. * Copyright (C) 2015 Igalia. @@ -27,7 +26,7 @@ // @internal -export function readableStreamReaderGenericInitialize(reader, stream) { +export function readableStreamReaderGenericInitialize(reader: ReadableStreamDefaultReader, stream: ReadableStream) { $putByIdDirectPrivate(reader, "ownerReadableStream", stream); $putByIdDirectPrivate(stream, "reader", reader); if ($getByIdDirectPrivate(stream, "state") === $streamReadable) @@ -44,7 +43,13 @@ export function readableStreamReaderGenericInitialize(reader, stream) { } } -export function privateInitializeReadableStreamDefaultController(this, stream, underlyingSource, size, highWaterMark) { +export function privateInitializeReadableStreamDefaultController( + this: ReadableStreamDefaultController, + stream: ReadableStream, + underlyingSource: UnderlyingSource, + size: QueuingStrategySize, + highWaterMark: QueuingStrategyHighWaterMark, +) { if (!$isReadableStream(stream)) throw new TypeError("ReadableStreamDefaultController needs a ReadableStream"); // readableStreamController is initialized with null value. @@ -92,7 +97,7 @@ export function readableStreamPipeTo(stream, sink) { } try { sink.enqueue(result.value); - } catch (e) { + } catch { sink.error("ReadableStream chunk enqueueing in the sink failed"); return; } @@ -336,12 +341,12 @@ export function pipeToDoReadWrite(pipeState) { () => {}, ); }, - e => { + _e => { pipeState.pendingReadPromiseCapability.resolve.$call(undefined, false); }, ); }, - e => { + _e => { pipeState.pendingReadPromiseCapability.resolve.$call(undefined, false); }, ); @@ -685,7 +690,7 @@ export function readDirectStream(stream, sink, underlyingSource) { if ($isPromise(prom)) { $markPromiseAsHandled(prom); } - } catch (e) {} + } catch {} underlyingSource = undefined; } @@ -743,8 +748,6 @@ export function assignToStream(stream, sink) { if (underlyingSource) { try { return $readDirectStream(stream, sink, underlyingSource); - } catch (e) { - throw e; } finally { underlyingSource = undefined; stream = undefined; @@ -755,7 +758,7 @@ export function assignToStream(stream, sink) { return $readStreamIntoSink(stream, sink, true); } -export async function readStreamIntoSink(stream, sink, isNative) { +export async function readStreamIntoSink(stream: ReadableStream, sink, isNative) { var didClose = false; var didThrow = false; var started = false; @@ -785,7 +788,6 @@ export async function readStreamIntoSink(stream, sink, isNative) { didClose = true; return sink.end(); } - var wroteCount = many.value.length; if (!started) { if (isNative) $startDirectStream.$call(sink, stream, undefined, onSinkClose, stream.$asyncContext); @@ -820,7 +822,7 @@ export async function readStreamIntoSink(stream, sink, isNative) { if ($isPromise(prom)) { $markPromiseAsHandled(prom); } - } catch (j) {} + } catch {} if (sink && !didClose) { didClose = true; @@ -836,7 +838,7 @@ export async function readStreamIntoSink(stream, sink, isNative) { if (reader) { try { reader.releaseLock(); - } catch (e) {} + } catch {} reader = undefined; } sink = undefined; @@ -872,7 +874,7 @@ export function handleDirectStreamError(e) { $putByIdDirectPrivate(controller, "sink", undefined); try { sink.close(e); - } catch (f) {} + } catch {} } this.error = this.flush = this.write = this.close = this.end = $onReadableStreamDirectControllerClosed; @@ -880,7 +882,7 @@ export function handleDirectStreamError(e) { if (typeof this.$underlyingSource.close === "function") { try { this.$underlyingSource.close.$call(this.$underlyingSource, e); - } catch (e) {} + } catch {} } try { @@ -889,7 +891,7 @@ export function handleDirectStreamError(e) { controller._pendingRead = undefined; $rejectPromise(pend, e); } - } catch (f) {} + } catch {} var stream = controller.$controlledReadableStream; if (stream) $readableStreamError(stream, e); } @@ -899,7 +901,7 @@ export function handleDirectStreamErrorReject(e) { return Promise.$reject(e); } -export function onPullDirectStream(controller) { +export function onPullDirectStream(controller: ReadableStreamDirectController) { var stream = controller.$controlledReadableStream; if (!stream || $getByIdDirectPrivate(stream, "state") !== $streamReadable) return; @@ -978,7 +980,7 @@ export function noopDoneFunction() { return Promise.$resolve({ value: undefined, done: true }); } -export function onReadableStreamDirectControllerClosed(reason) { +export function onReadableStreamDirectControllerClosed(_reason) { $throwTypeError("ReadableStreamDirectController is now closed"); } @@ -1034,7 +1036,7 @@ export function onCloseDirectStream(reason) { if (typeof this.$underlyingSource.close === "function") { try { this.$underlyingSource.close.$call(this.$underlyingSource, reason); - } catch (e) {} + } catch {} } var flushed; @@ -1123,7 +1125,7 @@ export function onFlushDirectStream() { } } -export function createTextStream(highWaterMark) { +export function createTextStream(_highWaterMark: number) { var sink; var array = []; var hasString = false; @@ -1233,14 +1235,14 @@ export function createTextStream(highWaterMark) { calledDone = true; sink.fulfill(); } - } catch (e) {} + } catch {} }, }; return [sink, capability]; } -export function initializeTextStream(underlyingSource, highWaterMark) { +export function initializeTextStream(underlyingSource, highWaterMark: number) { var [sink, closingPromise] = $createTextStream(highWaterMark); var controller = { @@ -1267,7 +1269,7 @@ export function initializeTextStream(underlyingSource, highWaterMark) { return closingPromise; } -export function initializeArrayStream(underlyingSource, highWaterMark) { +export function initializeArrayStream(underlyingSource, _highWaterMark: number) { var array = []; var closingPromise = $newPromiseCapability(Promise); var calledDone = false; @@ -1327,7 +1329,7 @@ export function initializeArrayStream(underlyingSource, highWaterMark) { return closingPromise; } -export function initializeArrayBufferStream(underlyingSource, highWaterMark) { +export function initializeArrayBufferStream(underlyingSource, highWaterMark: number) { // This is the fallback implementation for direct streams // When we don't know what the destination type is // We assume it is a Uint8Array. @@ -1467,7 +1469,7 @@ export function readableStreamReaderGenericCancel(reader, reason) { return $readableStreamCancel(stream, reason); } -export function readableStreamCancel(stream, reason) { +export function readableStreamCancel(stream: ReadableStream, reason: any) { stream.$disturbed = true; const state = $getByIdDirectPrivate(stream, "state"); if (state === $streamClosed) return Promise.$resolve(); @@ -1707,7 +1709,7 @@ export function readableStreamFromAsyncIterator(target, fn) { }, async pull(controller) { - var closingError, value, done, immediateTask; + var closingError: Error | undefined, value, done, immediateTask; try { while (!cancelled && !done) { @@ -1752,6 +1754,7 @@ export function readableStreamFromAsyncIterator(target, fn) { await iter.throw?.(closingError); } finally { iter = undefined; + // eslint-disable-next-line no-throw-literal throw closingError; } } else { @@ -1769,7 +1772,7 @@ export function readableStreamFromAsyncIterator(target, fn) { export function createLazyLoadedStreamPrototype(): typeof ReadableStreamDefaultController { const closer = [false]; - function callClose(controller) { + function callClose(controller: ReadableStreamDefaultController) { try { var source = controller.$underlyingSource; const stream = $getByIdDirectPrivate(controller, "controlledReadableStream"); @@ -1840,18 +1843,23 @@ export function createLazyLoadedStreamPrototype(): typeof ReadableStreamDefaultC } } - #controller: WeakRef; + #controller?: WeakRef; + // eslint-disable-next-line no-unused-vars pull; + // eslint-disable-next-line no-unused-vars cancel; + // eslint-disable-next-line no-unused-vars start; autoAllocateChunkSize = 0; - #chunk; #closed = false; $data?: Uint8Array; + // @ts-ignore-next-line + $stream: ReadableStream; + #onClose() { this.#closed = true; this.#controller = undefined; @@ -1925,6 +1933,7 @@ export function createLazyLoadedStreamPrototype(): typeof ReadableStreamDefaultC throw $ERR_INVALID_STATE("Internal error: invalid result from pull. This is a bug in Bun. Please report it."); } + // eslint-disable-next-line no-unused-private-class-members #pull(controller) { var handle = $getByIdDirectPrivate(this, "stream"); @@ -1977,6 +1986,7 @@ export function createLazyLoadedStreamPrototype(): typeof ReadableStreamDefaultC } } + // eslint-disable-next-line no-unused-private-class-members #cancel(reason) { var handle = $getByIdDirectPrivate(this, "stream"); this.$data = undefined; @@ -2090,8 +2100,9 @@ export function withoutUTF8BOM(result) { return result; } -export function readableStreamIntoText(stream) { - const [textStream, closer] = $createTextStream($getByIdDirectPrivate(stream, "highWaterMark")); +export function readableStreamIntoText(stream: ReadableStream) { + const highWaterMark = $getByIdDirectPrivate(stream, "highWaterMark"); + const [textStream, closer] = $createTextStream(highWaterMark); const prom = $readStreamIntoSink(stream, textStream, false); if (prom && $isPromise(prom)) { @@ -2101,7 +2112,11 @@ export function readableStreamIntoText(stream) { return closer.promise.$then($withoutUTF8BOM); } -export function readableStreamToArrayBufferDirect(stream, underlyingSource, asUint8Array) { +export function readableStreamToArrayBufferDirect( + stream: ReadableStream, + underlyingSource: any, + asUint8Array: boolean, +) { var sink = new Bun.ArrayBufferSink(); $putByIdDirectPrivate(stream, "underlyingSource", undefined); var highWaterMark = $getByIdDirectPrivate(stream, "highWaterMark"); @@ -2113,7 +2128,7 @@ export function readableStreamToArrayBufferDirect(stream, underlyingSource, asUi var controller = { start() {}, - close(reason) { + close(_reason) { if (!ended) { ended = true; if (close) { @@ -2181,7 +2196,7 @@ export async function readableStreamToTextDirect(stream, underlyingSource) { try { reader.releaseLock(); - } catch (e) {} + } catch {} reader = undefined; stream = undefined; @@ -2202,12 +2217,10 @@ export async function readableStreamToArrayDirect(stream, underlyingSource) { try { reader.releaseLock(); - } catch (e) {} + } catch {} reader = undefined; return Promise.$resolve(capability.promise); - } catch (e) { - throw e; } finally { stream = undefined; reader = undefined; @@ -2237,6 +2250,7 @@ export function readableStreamDefineLazyIterators(prototype) { } } catch (e) { deferredError = e; + throw e; } finally { reader.releaseLock(); @@ -2246,10 +2260,6 @@ export function readableStreamDefineLazyIterators(prototype) { $markPromiseAsHandled(promise); } } - - if (deferredError) { - throw deferredError; - } } }; var createAsyncIterator = function asyncIterator() { diff --git a/src/js/builtins/shell.ts b/src/js/builtins/shell.ts index a88f4a6fec..2b52695099 100644 --- a/src/js/builtins/shell.ts +++ b/src/js/builtins/shell.ts @@ -1,10 +1,14 @@ -import type { ShellOutput } from "bun"; +export function createBunShellTemplateFunction(createShellInterpreter_, createParsedShellScript_) { + const createShellInterpreter = createShellInterpreter_ as ( + resolve: (code: number, stdout: Buffer, stderr: Buffer) => void, + reject: (code: number, stdout: Buffer, stderr: Buffer) => void, + args: $ZigGeneratedClasses.ParsedShellScript, + ) => $ZigGeneratedClasses.ShellInterpreter; + const createParsedShellScript = createParsedShellScript_ as ( + raw: string, + args: string[], + ) => $ZigGeneratedClasses.ParsedShellScript; -type ShellInterpreter = any; -type ParsedShellScript = any; -type Resolve = (value: ShellOutput) => void; - -export function createBunShellTemplateFunction(createShellInterpreter, createParsedShellScript) { function lazyBufferToHumanReadableString(this: Buffer) { return this.toString(); } @@ -99,18 +103,14 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar } } - function autoStartShell(shell) { - return shell.run(); - } - class ShellPromise extends Promise { - #args: ParsedShellScript | undefined = undefined; + #args: $ZigGeneratedClasses.ParsedShellScript | undefined = undefined; #hasRun: boolean = false; #throws: boolean = true; - #resolve: Function; - #reject: Function; + #resolve: (code: number, stdout: Buffer, stderr: Buffer) => void; + #reject: (code: number, stdout: Buffer, stderr: Buffer) => void; - constructor(args: ParsedShellScript, throws: boolean) { + constructor(args: $ZigGeneratedClasses.ParsedShellScript, throws: boolean) { // Create the error immediately so it captures the stacktrace at the point // of the shell script's invocation. Just creating the error should be // relatively cheap, the costly work is actually computing the stacktrace @@ -151,7 +151,7 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar if (typeof newCwd === "undefined" || newCwd === "." || newCwd === "" || newCwd === "./") { newCwd = defaultCwd; } - this.#args.setCwd(newCwd); + this.#args!.setCwd(newCwd); return this; } @@ -161,7 +161,7 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar newEnv = defaultEnv; } - this.#args.setEnv(newEnv); + this.#args!.setEnv(newEnv); return this; } @@ -169,16 +169,15 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar if (!this.#hasRun) { this.#hasRun = true; - let interp = createShellInterpreter(this.#resolve, this.#reject, this.#args); + let interp = createShellInterpreter(this.#resolve, this.#reject, this.#args!); this.#args = undefined; interp.run(); - interp = undefined; } } #quiet(): this { this.#throwIfRunning(); - this.#args.setQuiet(); + this.#args!.setQuiet(); return this; } diff --git a/src/js/bun/sql.ts b/src/js/bun/sql.ts index 3e723faef0..dd88169c35 100644 --- a/src/js/bun/sql.ts +++ b/src/js/bun/sql.ts @@ -1,5 +1,4 @@ -const { hideFromStack } = require("internal/shared"); -const defineProperties = Object.defineProperties; +import type * as BunTypes from "bun"; const enum QueryStatus { active = 1 << 1, @@ -19,6 +18,9 @@ const enum SSLMode { verify_full = 4, } +const { hideFromStack } = require("internal/shared"); +const defineProperties = Object.defineProperties; + function connectionClosedError() { return $ERR_POSTGRES_CONNECTION_CLOSED("Connection closed"); } @@ -66,12 +68,7 @@ const _results = Symbol("results"); const PublicPromise = Promise; type TransactionCallback = (sql: (strings: string, ...values: any[]) => Query) => Promise; -const { - createConnection: _createConnection, - createQuery, - PostgresSQLConnection, - init, -} = $zig("postgres.zig", "createBinding"); +const { createConnection: _createConnection, createQuery, init } = $zig("postgres.zig", "createBinding"); function normalizeSSLMode(value: string): SSLMode { if (!value) { @@ -490,6 +487,8 @@ class Query extends PublicPromise { if (!handle) return this; if (async) { + // Ensure it's actually async + // eslint-disable-next-line await 1; } @@ -624,7 +623,7 @@ init( } try { query.resolve(query[_results]); - } catch (e) {} + } catch {} return; } $assert(result instanceof SQLResultArray, "Invalid result array"); @@ -674,7 +673,7 @@ init( } try { query.resolve(result); - } catch (e) {} + } catch {} }, function onRejectPostgresQuery(query, reject, queries) { if (queries) { @@ -686,7 +685,7 @@ init( try { query.reject(reject); - } catch (e) {} + } catch {} }, ); @@ -711,7 +710,7 @@ enum PooledConnectionFlags { class PooledConnection { pool: ConnectionPool; - connection: ReturnType | null = null; + connection: $ZigGeneratedClasses.PostgresSQLConnection | null = null; state: PooledConnectionState = PooledConnectionState.pending; storedError: Error | null = null; queries: Set<(err: Error) => void> = new Set(); @@ -781,11 +780,11 @@ class PooledConnection { this.#startConnection(); } async #startConnection() { - this.connection = await createConnection( + this.connection = (await createConnection( this.connectionInfo, this.#onConnected.bind(this), this.#onClose.bind(this), - ); + )) as $ZigGeneratedClasses.PostgresSQLConnection; } onClose(onClose: (err: Error) => void) { this.queries.add(onClose); @@ -1282,7 +1281,7 @@ async function createConnection(options, onConnected, onClose) { connectionTimeout, maxLifetime, !prepare, - ); + ) as $ZigGeneratedClasses.PostgresSQLConnection; } catch (e) { onClose(e); } @@ -1522,12 +1521,12 @@ function loadOptions(o) { if (sslMode !== SSLMode.disable && !tls?.serverName) { if (hostname) { tls = { ...tls, serverName: hostname }; - } else if (!!tls) { + } else if (tls) { tls = true; } } - if (!!tls && sslMode === SSLMode.disable) { + if (tls && sslMode === SSLMode.disable) { sslMode = SSLMode.prefer; } port = Number(port); @@ -1721,7 +1720,7 @@ function SQL(o, e = {}) { } function onReserveConnected(err, pooledConnection) { - const { promise, resolve, reject } = this; + const { resolve, reject } = this; if (err) { return reject(err); } @@ -1746,7 +1745,7 @@ function SQL(o, e = {}) { } if ($isArray(strings)) { // detect if is tagged template - if (!$isArray(strings.raw)) { + if (!$isArray((strings as unknown as TemplateStringsArray).raw)) { return new SQLArrayParameter(strings, values); } } else if ( @@ -2079,7 +2078,7 @@ function SQL(o, e = {}) { } if ($isArray(strings)) { // detect if is tagged template - if (!$isArray(strings.raw)) { + if (!$isArray((strings as unknown as TemplateStringsArray).raw)) { return new SQLArrayParameter(strings, values); } } else if ( @@ -2246,7 +2245,7 @@ function SQL(o, e = {}) { } } if (distributed) { - transaction_sql.savepoint = async (fn: TransactionCallback, name?: string): Promise => { + transaction_sql.savepoint = async (_fn: TransactionCallback, _name?: string): Promise => { throw $ERR_POSTGRES_INVALID_TRANSACTION_STATE("cannot call savepoint inside a distributed transaction"); }; } else { @@ -2313,7 +2312,7 @@ function SQL(o, e = {}) { function sql(strings, ...values) { if ($isArray(strings)) { // detect if is tagged template - if (!$isArray(strings.raw)) { + if (!$isArray((strings as unknown as TemplateStringsArray).raw)) { return new SQLArrayParameter(strings, values); } } else if (typeof strings === "object" && !(strings instanceof Query) && !(strings instanceof SQLArrayParameter)) { @@ -2459,7 +2458,7 @@ function SQL(o, e = {}) { return sql; } -var lazyDefaultSQL; +var lazyDefaultSQL: InstanceType; function resetDefaultSQL(sql) { lazyDefaultSQL = sql; @@ -2474,8 +2473,7 @@ function ensureDefaultSQL() { } } -var initialDefaultSQL; -var defaultSQLObject = (initialDefaultSQL = function sql(strings, ...values) { +var defaultSQLObject: InstanceType = function sql(strings, ...values) { if (new.target) { return SQL(strings); } @@ -2483,7 +2481,7 @@ var defaultSQLObject = (initialDefaultSQL = function sql(strings, ...values) { resetDefaultSQL(SQL(undefined)); } return lazyDefaultSQL(strings, ...values); -}); +} as typeof BunTypes.SQL; defaultSQLObject.reserve = (...args) => { ensureDefaultSQL(); @@ -2512,21 +2510,21 @@ defaultSQLObject.unsafe = (...args) => { return lazyDefaultSQL.unsafe(...args); }; -defaultSQLObject.file = async (...args) => { +defaultSQLObject.file = (filename: string, ...args) => { ensureDefaultSQL(); - return lazyDefaultSQL.file(...args); + return lazyDefaultSQL.file(filename, ...args); }; -defaultSQLObject.transaction = defaultSQLObject.begin = (...args) => { +defaultSQLObject.transaction = defaultSQLObject.begin = function (...args: Parameters) { ensureDefaultSQL(); return lazyDefaultSQL.begin(...args); -}; +} as (typeof BunTypes.SQL)["begin"]; -defaultSQLObject.end = defaultSQLObject.close = (...args) => { +defaultSQLObject.end = defaultSQLObject.close = (...args: Parameters) => { ensureDefaultSQL(); return lazyDefaultSQL.close(...args); }; -defaultSQLObject.flush = (...args) => { +defaultSQLObject.flush = (...args: Parameters) => { ensureDefaultSQL(); return lazyDefaultSQL.flush(...args); }; diff --git a/src/js/bun/sqlite.ts b/src/js/bun/sqlite.ts index 3995e947c8..6253fdf19f 100644 --- a/src/js/bun/sqlite.ts +++ b/src/js/bun/sqlite.ts @@ -1,4 +1,5 @@ // Hardcoded module "sqlite" +import type * as SqliteTypes from "bun:sqlite"; const kSafeIntegersFlag = 1 << 1; const kStrictFlag = 1 << 2; @@ -123,11 +124,11 @@ class Statement { #raw; - get; - all; - iterate; - values; - run; + get: SqliteTypes.Statement["get"]; + all: SqliteTypes.Statement["all"]; + iterate: SqliteTypes.Statement["iterate"]; + values: SqliteTypes.Statement["values"]; + run: SqliteTypes.Statement["run"]; isFinalized = false; toJSON() { @@ -190,6 +191,7 @@ class Statement { return this; } + // eslint-disable-next-line no-unused-private-class-members #get(...args) { if (args.length === 0) return this.#getNoArgs(); var arg0 = args[0]; @@ -202,6 +204,7 @@ class Statement { : this.#raw.get(...args); } + // eslint-disable-next-line no-unused-private-class-members #all(...args) { if (args.length === 0) return this.#allNoArgs(); var arg0 = args[0]; @@ -214,6 +217,7 @@ class Statement { : this.#raw.all(...args); } + // eslint-disable-next-line no-unused-private-class-members *#iterate(...args) { if (args.length === 0) return yield* this.#iterateNoArgs(); var arg0 = args[0]; @@ -230,6 +234,7 @@ class Statement { } } + // eslint-disable-next-line no-unused-private-class-members #values(...args) { if (args.length === 0) return this.#valuesNoArgs(); var arg0 = args[0]; @@ -242,11 +247,13 @@ class Statement { : this.#raw.values(...args); } + // eslint-disable-next-line no-unused-private-class-members #run(...args) { if (args.length === 0) { this.#runNoArgs(); return createChangesObject(); } + var arg0 = args[0]; !isArray(arg0) && (!arg0 || typeof arg0 !== "object" || isTypedArray(arg0)) @@ -296,17 +303,12 @@ class Database { this.#internalFlags |= kSafeIntegersFlag; } - if (options.readonly) { + if (options.readonly) { deserializeFlags |= constants.SQLITE_DESERIALIZE_READONLY; } } - this.#handle = Database.#deserialize( - filenameGiven, - this.#internalFlags, - deserializeFlags - - ); + this.#handle = Database.#deserialize(filenameGiven, this.#internalFlags, deserializeFlags); this.filename = ":memory:"; return; @@ -367,9 +369,9 @@ class Database { #internalFlags = 0; #handle; - #cachedQueriesKeys = []; - #cachedQueriesLengths = []; - #cachedQueriesValues = []; + #cachedQueriesKeys: string[] = []; + #cachedQueriesLengths: number[] = []; + #cachedQueriesValues: Statement[] = []; filename; #hasClosed = false; get handle() { @@ -400,7 +402,10 @@ class Database { return SQL.deserialize(serialized, openFlags, deserializeFlags); } - static deserialize(serialized, options: boolean | { readonly?: boolean; strict?: boolean; safeIntegers?: boolean } = false) { + static deserialize( + serialized, + options: boolean | { readonly?: boolean; strict?: boolean; safeIntegers?: boolean } = false, + ) { if (typeof options === "boolean") { // Maintain backward compatibility with existing API return new Database(serialized, { readonly: options }); @@ -425,7 +430,7 @@ class Database { return SQL.setCustomSQLite(path); } - fileControl(cmd, arg) { + fileControl(_cmd, _arg) { const handle = this.#handle; if (arguments.length <= 2) { @@ -485,14 +490,14 @@ class Database { const willCache = this.#cachedQueriesKeys.length < Database.MAX_QUERY_CACHE_SIZE; // this list should be pretty small - var index = this.#cachedQueriesLengths.indexOf(query.length); + let index = this.#cachedQueriesLengths.indexOf(query.length); while (index !== -1) { if (this.#cachedQueriesKeys[index] !== query) { index = this.#cachedQueriesLengths.indexOf(query.length, index + 1); continue; } - var stmt = this.#cachedQueriesValues[index]; + const stmt = this.#cachedQueriesValues[index]; if (stmt.isFinalized) { return (this.#cachedQueriesValues[index] = this.prepare( query, @@ -550,7 +555,7 @@ class Database { Database.prototype.exec = Database.prototype.run; // Return the database's cached transaction controller, or create a new one -const getController = (db, self) => { +const getController = (db, _self) => { let controller = (controllers ||= new WeakMap()).get(db); if (!controller) { const shared = { diff --git a/src/js/internal/assert/myers_diff.ts b/src/js/internal/assert/myers_diff.ts index 63d0fb45d8..f47b61c41a 100644 --- a/src/js/internal/assert/myers_diff.ts +++ b/src/js/internal/assert/myers_diff.ts @@ -55,7 +55,7 @@ function printSimpleMyersDiff(diff: Diff[]) { return `\n${message}`; } -function printMyersDiff(diff: Diff[], simple = false) { +function printMyersDiff(diff: Diff[], _simple = false) { let message = ""; let skipped = false; let nopCount = 0; diff --git a/src/js/internal/assert/utils.ts b/src/js/internal/assert/utils.ts index f5dfa91263..203881c904 100644 --- a/src/js/internal/assert/utils.ts +++ b/src/js/internal/assert/utils.ts @@ -147,7 +147,7 @@ function loadAssertionError() { // throw null; // } -function getErrMessage(message: string, value: unknown, fn: Function): string | undefined { +function getErrMessage(_message: string, _value: unknown, _fn: Function): string | undefined { // const tmpLimit = Error.stackTraceLimit; // const errorStackTraceLimitIsWritable = isErrorStackTraceLimitWritable(); // Make sure the limit is set to 1. Otherwise it could fail (<= 0) or it diff --git a/src/js/internal/cluster/RoundRobinHandle.ts b/src/js/internal/cluster/RoundRobinHandle.ts index edcc00178e..bc894cefc2 100644 --- a/src/js/internal/cluster/RoundRobinHandle.ts +++ b/src/js/internal/cluster/RoundRobinHandle.ts @@ -35,7 +35,7 @@ export default class RoundRobinHandle { port, host: address, // Currently, net module only supports `ipv6Only` option in `flags`. - ipv6Only: Boolean(flags & UV_TCP_IPV6ONLY), + ipv6Only: !!(flags & UV_TCP_IPV6ONLY), backlog, }); } else diff --git a/src/js/internal/cluster/child.ts b/src/js/internal/cluster/child.ts index ca30515ba8..4d2c8897cd 100644 --- a/src/js/internal/cluster/child.ts +++ b/src/js/internal/cluster/child.ts @@ -163,7 +163,7 @@ function rr(message, { indexesKey, index }, cb) { } } - function listen(backlog) { + function listen(_backlog) { // TODO(bnoordhuis) Send a message to the primary that tells it to // update the backlog size. The actual backlog should probably be // the largest requested size by any worker. diff --git a/src/js/internal/cluster/primary.ts b/src/js/internal/cluster/primary.ts index 49a35354c5..9a046c8a87 100644 --- a/src/js/internal/cluster/primary.ts +++ b/src/js/internal/cluster/primary.ts @@ -208,7 +208,7 @@ const methodMessageMapping = { queryServer, }; -function onmessage(message, handle) { +function onmessage(message, _handle) { const worker = this; const fn = methodMessageMapping[message.act]; diff --git a/src/js/internal/debugger.ts b/src/js/internal/debugger.ts index d8b0d0bf9e..f7c7a7b6af 100644 --- a/src/js/internal/debugger.ts +++ b/src/js/internal/debugger.ts @@ -287,7 +287,7 @@ class Debugger { } socket.data.framer.onData(socket, bytes); }, - drain: socket => {}, + drain: _socket => {}, close: socket => { if (socket.data) { const { backend, framer } = socket.data; @@ -433,7 +433,7 @@ async function connectToUnixServer( hostname, port: Number(port), }; - } catch (error) { + } catch { exit("Invalid tcp: URL:" + unix); return; } @@ -493,7 +493,7 @@ async function connectToUnixServer( }, }).catch(error => { // Force it to close - const backendRaw = createBackend(executionContextId, true, (...messages: string[]) => {}); + const backendRaw = createBackend(executionContextId, true, () => {}); close.$call(backendRaw); $debug("error:", error); diff --git a/src/js/internal/errors.ts b/src/js/internal/errors.ts index b0e84f460e..50bb754512 100644 --- a/src/js/internal/errors.ts +++ b/src/js/internal/errors.ts @@ -3,7 +3,7 @@ const { SafeArrayIterator } = require("internal/primordials"); const ArrayIsArray = Array.isArray; const ArrayPrototypePush = Array.prototype.push; -function aggregateTwoErrors(innerError, outerError) { +function aggregateTwoErrors(innerError: Error | undefined, outerError: Error & { errors?: Error[] }) { if (innerError && outerError && innerError !== outerError) { if (ArrayIsArray(outerError.errors)) { // If `outerError` is already an `AggregateError`. diff --git a/src/js/internal/fs/streams.ts b/src/js/internal/fs/streams.ts index e110f5057a..674e24651f 100644 --- a/src/js/internal/fs/streams.ts +++ b/src/js/internal/fs/streams.ts @@ -2,7 +2,7 @@ import type { FileSink } from "bun"; const { Readable, Writable, finished } = require("node:stream"); const fs: typeof import("node:fs") = require("node:fs"); -const { open, read, write, fsync, writev } = fs; +const { read, write, fsync, writev } = fs; const { FileHandle, kRef, kUnref, kFd } = (fs.promises as any).$data as { FileHandle: { new (): FileHandle }; readonly kRef: unique symbol; @@ -41,8 +41,6 @@ const { validateInteger, validateInt32, validateFunction } = require("internal/v // `new Response(Bun.file("path.txt"))`. // This makes an idomatic Node.js pattern much faster. const kReadStreamFastPath = Symbol("kReadStreamFastPath"); -const kWriteStreamFastPathClosed = Symbol("kWriteStreamFastPathClosed"); -const kWriteFastSimpleBuffering = Symbol("writeFastSimpleBuffering"); // Bun supports a fast path for `createWriteStream("path.txt")` where instead of // using `node:fs`, `Bun.file(...).writer()` is used instead. const kWriteStreamFastPath = Symbol("kWriteStreamFastPath"); diff --git a/src/js/internal/html.ts b/src/js/internal/html.ts index 65ce8caa4c..80373ae9c4 100644 --- a/src/js/internal/html.ts +++ b/src/js/internal/html.ts @@ -223,7 +223,7 @@ yourself with Bun.serve(). // use the default port via existing port detection code. // port: 3000, - fetch(req: Request) { + fetch(_req: Request) { return new Response("Not found", { status: 404 }); }, }); @@ -242,7 +242,7 @@ yourself with Bun.serve(). // Retry with a different port up to 4 times. port: defaultPort++, - fetch(req: Request) { + fetch(_req: Request) { return new Response("Not found", { status: 404 }); }, }); diff --git a/src/js/internal/shared.ts b/src/js/internal/shared.ts index ae29c54452..863893ea03 100644 --- a/src/js/internal/shared.ts +++ b/src/js/internal/shared.ts @@ -7,7 +7,7 @@ class NotImplementedError extends Error { feature + " is not yet implemented in Bun." + (issue ? " Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/" + issue : "") + - (!!extra ? ". " + extra : ""), + (extra ? ". " + extra : ""), ); this.name = "NotImplementedError"; this.code = "ERR_NOT_IMPLEMENTED"; diff --git a/src/js/internal/streams/duplex.ts b/src/js/internal/streams/duplex.ts index b7e247b7b4..41a8731bda 100644 --- a/src/js/internal/streams/duplex.ts +++ b/src/js/internal/streams/duplex.ts @@ -150,4 +150,4 @@ Duplex.from = function (body) { return duplexify(body, "body"); }; -export default Duplex as any as typeof import("node:stream").Duplex; +export default Duplex as unknown as typeof import("node:stream").Duplex; diff --git a/src/js/internal/streams/native-readable.ts b/src/js/internal/streams/native-readable.ts index 1237d8bdbd..167f35644c 100644 --- a/src/js/internal/streams/native-readable.ts +++ b/src/js/internal/streams/native-readable.ts @@ -181,7 +181,7 @@ function handleResult(stream: NativeReadable, result: any, chunk: Buffer, isClos process.nextTick(() => { stream.push(null); }); - return (chunk?.byteLength ?? 0 > 0) ? chunk : undefined; + return (chunk?.byteLength ?? 0) > 0 ? chunk : undefined; } else if ($isTypedArrayView(result)) { if (result.byteLength >= stream[kHighWaterMark] && !stream[kHasResized] && !isClosed) { adjustHighWaterMark(stream); diff --git a/src/js/internal/streams/readable.ts b/src/js/internal/streams/readable.ts index c31c05fb9e..63bfb17f63 100644 --- a/src/js/internal/streams/readable.ts +++ b/src/js/internal/streams/readable.ts @@ -817,7 +817,7 @@ function maybeReadMore_(stream, state) { // call cb(er, data) where data is <= n in length. // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. -Readable.prototype._read = function (n) { +Readable.prototype._read = function (_n) { throw $ERR_METHOD_NOT_IMPLEMENTED("_read()"); }; @@ -1268,9 +1268,9 @@ async function* createAsyncIterator(stream, options) { stream.on("readable", next); - let error; + let error: Error | null; const cleanup = eos(stream, { writable: false }, err => { - error = err ? aggregateTwoErrors(error, err) : null; + error = err ? aggregateTwoErrors(error as Error, err) : null; callback(); callback = nop; }); @@ -1288,8 +1288,8 @@ async function* createAsyncIterator(stream, options) { await new Promise(next); } } - } catch (err) { - error = aggregateTwoErrors(error, err); + } catch (err: unknown) { + error = aggregateTwoErrors(error as Error, err as Error); throw error; } finally { if ((error || options?.destroyOnReturn !== false) && (error === undefined || stream._readableState.autoDestroy)) { @@ -1647,4 +1647,4 @@ Readable.wrap = function (src, options) { }).wrap(src); }; -export default Readable; +export default Readable as unknown as typeof import("node:stream").Readable; diff --git a/src/js/internal/streams/transform.ts b/src/js/internal/streams/transform.ts index 9cd3729018..ce6d43ec6f 100644 --- a/src/js/internal/streams/transform.ts +++ b/src/js/internal/streams/transform.ts @@ -125,7 +125,7 @@ function prefinish() { Transform.prototype._final = final; -Transform.prototype._transform = function (chunk, encoding, callback) { +Transform.prototype._transform = function (_chunk, _encoding, _callback) { throw $ERR_METHOD_NOT_IMPLEMENTED("_transform()"); }; diff --git a/src/js/internal/streams/writable.ts b/src/js/internal/streams/writable.ts index 3d86b0771b..c1c9d4ba63 100644 --- a/src/js/internal/streams/writable.ts +++ b/src/js/internal/streams/writable.ts @@ -1120,4 +1120,4 @@ Writable.prototype[SymbolAsyncDispose] = function () { ); }; -export default Writable; +export default Writable as unknown as typeof import("node:stream").Writable; diff --git a/src/js/internal/tty.ts b/src/js/internal/tty.ts index a0adc4414a..9191ad4330 100644 --- a/src/js/internal/tty.ts +++ b/src/js/internal/tty.ts @@ -150,7 +150,7 @@ function getColorDepth(env: NodeJS.ProcessEnv) { const TERM = env.TERM; if (TERM) { - if (/^xterm-256/.test(TERM) !== null) { + if (TERM.startsWith("xterm-256") !== null) { return COLORS_256; } diff --git a/src/js/internal/util/inspect.js b/src/js/internal/util/inspect.js index 106ff19a0b..86d80102d3 100644 --- a/src/js/internal/util/inspect.js +++ b/src/js/internal/util/inspect.js @@ -30,7 +30,6 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. - const { pathToFileURL } = require("node:url"); let BufferModule; @@ -204,7 +203,6 @@ const { isStringObject, isNumberObject, isBooleanObject, - //isBigIntObject, } = require("node:util/types"); //! temp workaround to apply is{BigInt,Symbol}Object fix @@ -464,7 +462,6 @@ const coreModuleRegExp = /^ {4}at (?:[^/\\(]+ \(|)node:(.+):\d+:\d+\)?$/; const nodeModulesRegExp = /[/\\]node_modules[/\\](.+?)(?=[/\\])/g; const classRegExp = /^(\s+[^(]*?)\s*{/; -// eslint-disable-next-line node-core/no-unescaped-regexp-dot const stripCommentsRegExp = /(\/\/.*?\n)|(\/\*(.|\n)*?\*\/)/g; const kMinLineLength = 16; @@ -1940,15 +1937,6 @@ function groupArrayElements(ctx, output, value) { return output; } -function handleMaxCallStackSize(ctx, err, constructorName, indentationLvl) { - ctx.seen.pop(); - ctx.indentationLvl = indentationLvl; - return ctx.stylize( - `[${constructorName}: Inspection interrupted ` + "prematurely. Maximum call stack size exceeded.]", - "special", - ); -} - function addNumericSeparator(integerString) { let result = ""; let i = integerString.length; diff --git a/src/js/internal/validators.ts b/src/js/internal/validators.ts index 9ab57ecd13..306ead7267 100644 --- a/src/js/internal/validators.ts +++ b/src/js/internal/validators.ts @@ -1,9 +1,6 @@ const { hideFromStack } = require("internal/shared"); const RegExpPrototypeExec = RegExp.prototype.exec; -const ArrayPrototypeIncludes = Array.prototype.includes; -const ArrayPrototypeJoin = Array.prototype.join; -const ArrayPrototypeMap = Array.prototype.map; const ArrayIsArray = Array.isArray; const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/; diff --git a/src/js/internal/webstreams_adapters.ts b/src/js/internal/webstreams_adapters.ts index 26c972e6f1..916bf812d8 100644 --- a/src/js/internal/webstreams_adapters.ts +++ b/src/js/internal/webstreams_adapters.ts @@ -14,7 +14,7 @@ const Duplex = require("internal/streams/duplex"); const { destroyer } = require("internal/streams/destroy"); const { isDestroyed, isReadable, isWritable, isWritableEnded } = require("internal/streams/utils"); const { Buffer } = require("node:buffer"); -const { kEmptyObject, kGetNativeReadableProto } = require("internal/shared"); +const { kEmptyObject } = require("internal/shared"); const { validateBoolean, validateObject } = require("internal/validators"); const finished = require("internal/streams/end-of-stream"); @@ -98,7 +98,7 @@ class ReadableFromWeb extends Readable { return; } - var deferredError; + var deferredError: Error | undefined; try { do { var done = false, @@ -134,10 +134,10 @@ class ReadableFromWeb extends Readable { } } while (!this.#closed); } catch (e) { - deferredError = e; - } finally { - if (deferredError) throw deferredError; + deferredError = e as Error; } + + if (deferredError) throw deferredError; } _destroy(error, callback) { @@ -511,7 +511,7 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj ); } -function newStreamReadableFromReadableStream(readableStream, options = kEmptyObject) { +function newStreamReadableFromReadableStream(readableStream, options: Record = kEmptyObject) { if (!$inheritsReadableStream(readableStream)) { throw $ERR_INVALID_ARG_TYPE("readableStream", "ReadableStream", readableStream); } diff --git a/src/js/node/async_hooks.ts b/src/js/node/async_hooks.ts index 8a06e26c8b..7096931917 100644 --- a/src/js/node/async_hooks.ts +++ b/src/js/node/async_hooks.ts @@ -101,8 +101,6 @@ class AsyncLocalStorage { set(context); try { return fn(...args); - } catch (error) { - throw error; } finally { set(prev); } @@ -173,8 +171,6 @@ class AsyncLocalStorage { $assert(this.getStore() === store_value, "run: store_value was not set"); try { return callback(...args); - } catch (e) { - throw e; } finally { // Note: early `return` will prevent `throw` above from working. I think... // Set AsyncContextFrame to undefined if we are out of context values @@ -243,7 +239,7 @@ class AsyncLocalStorage { // Node.js internal function. In Bun's implementation, calling this is not // observable from outside the AsyncLocalStorage implementation. - _propagate(resource, triggerResource, type) {} + _propagate(_resource, _triggerResource, _type) {} } if (IS_BUN_DEVELOPMENT) { @@ -306,8 +302,6 @@ class AsyncResource { set(this.#snapshot); try { return fn.$apply(thisArg, args); - } catch (error) { - throw error; } finally { set(prev); } diff --git a/src/js/node/child_process.ts b/src/js/node/child_process.ts index f5bdafc7be..eb80156ca7 100644 --- a/src/js/node/child_process.ts +++ b/src/js/node/child_process.ts @@ -1,6 +1,5 @@ // Hardcoded module "node:child_process" const EventEmitter = require("node:events"); -const StreamModule = require("node:stream"); const OsModule = require("node:os"); const { kHandle } = require("internal/shared"); const { @@ -24,7 +23,6 @@ var kEmptyObject = ObjectCreate(null); var signals = OsModule.constants.signals; var ArrayPrototypeJoin = Array.prototype.join; -var ArrayPrototypeMap = Array.prototype.map; var ArrayPrototypeIncludes = Array.prototype.includes; var ArrayPrototypeSlice = Array.prototype.slice; var ArrayPrototypeUnshift = Array.prototype.unshift; @@ -36,9 +34,7 @@ const ArrayPrototypePush = Array.prototype.push; var ArrayBufferIsView = ArrayBuffer.isView; var NumberIsInteger = Number.isInteger; - var StringPrototypeIncludes = String.prototype.includes; -var StringPrototypeSlice = String.prototype.slice; var Uint8ArrayPrototypeIncludes = Uint8Array.prototype.includes; const MAX_BUFFER = 1024 * 1024; @@ -524,7 +520,6 @@ function spawnSync(file, args, options) { var { stdout = null, stderr = null, - success, exitCode, signalCode, exitedDueToTimeout, @@ -721,7 +716,6 @@ function fork(modulePath, args = [], options) { modulePath = getValidatedPath(modulePath, "modulePath"); // Get options and args arguments. - let execArgv; if (args == null) { args = []; @@ -1464,7 +1458,7 @@ const nodeToBunLookup = { ipc: "ipc", }; -function nodeToBun(item: string, index: number): string | number | null { +function nodeToBun(item: string, index: number): string | number | null | NodeJS.TypedArray | ArrayBufferView { // If not defined, use the default. // For stdin/stdout/stderr, it's pipe. For others, it's ignore. if (item == null) { @@ -1735,7 +1729,6 @@ function toPathIfFileURL(fileURLOrPath) { //------------------------------------------------------------------------------ var Error = globalThis.Error; var TypeError = globalThis.TypeError; -var RangeError = globalThis.RangeError; function genericNodeError(message, errorProperties) { // eslint-disable-next-line no-restricted-syntax diff --git a/src/js/node/dgram.ts b/src/js/node/dgram.ts index 87192161e2..7251471c31 100644 --- a/src/js/node/dgram.ts +++ b/src/js/node/dgram.ts @@ -30,19 +30,21 @@ const CONNECT_STATE_CONNECTED = 2; const RECV_BUFFER = true; const SEND_BUFFER = false; -const LIBUS_LISTEN_DEFAULT = 0; -const LIBUS_LISTEN_EXCLUSIVE_PORT = 1; -const LIBUS_SOCKET_ALLOW_HALF_OPEN = 2; -const LIBUS_LISTEN_REUSE_PORT = 4; -const LIBUS_SOCKET_IPV6_ONLY = 8; -const LIBUS_LISTEN_REUSE_ADDR = 16; -const LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE = 32; +const enum uSockets { + LISTEN_DEFAULT = 0, + LISTEN_EXCLUSIVE_PORT = 1, + SOCKET_ALLOW_HALF_OPEN = 2, + LISTEN_REUSE_PORT = 4, + SOCKET_IPV6_ONLY = 8, + LISTEN_REUSE_ADDR = 16, + LISTEN_DISALLOW_REUSE_PORT_FAILURE = 32, +} const kStateSymbol = Symbol("state symbol"); const kOwnerSymbol = Symbol("owner symbol"); const async_id_symbol = Symbol("async_id_symbol"); -const { hideFromStack, throwNotImplemented } = require("internal/shared"); +const { throwNotImplemented } = require("internal/shared"); const { validateString, validateNumber, @@ -205,7 +207,7 @@ function createSocket(type, listener) { return new Socket(type, listener); } -function bufferSize(self, size, buffer) { +function bufferSize(self, size, _buffer) { if (size >>> 0 !== size) throw $ERR_SOCKET_BAD_BUFFER_SIZE(); const ctx = {}; @@ -276,15 +278,12 @@ Socket.prototype.bind = function (port_, address_ /* , callback */) { } let address; - let exclusive; if (port !== null && typeof port === "object") { address = port.address || ""; - exclusive = !!port.exclusive; port = port.port; } else { address = typeof address_ === "function" ? "" : address_; - exclusive = false; } // Defaulting address for bind to all interfaces @@ -303,19 +302,18 @@ Socket.prototype.bind = function (port_, address_ /* , callback */) { return; } - let flags = LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE; + let flags = uSockets.LISTEN_DISALLOW_REUSE_PORT_FAILURE; if (state.reuseAddr) { - flags |= LIBUS_LISTEN_REUSE_ADDR; + flags |= uSockets.LISTEN_REUSE_ADDR; } if (state.ipv6Only) { - flags |= LIBUS_SOCKET_IPV6_ONLY; + flags |= uSockets.SOCKET_IPV6_ONLY; } if (state.reusePort) { - exclusive = true; // TODO: cluster support - flags |= LIBUS_LISTEN_REUSE_PORT; + flags |= uSockets.LISTEN_REUSE_PORT; } // TODO flags @@ -503,7 +501,7 @@ function onListenSuccess() { clearQueue.$call(this); } -function onListenError(err) { +function onListenError(_err) { this.removeListener("listening", onListenSuccess); this[kStateSymbol].queue = undefined; } diff --git a/src/js/node/events.ts b/src/js/node/events.ts index ec6e1410ea..88c64e7c8e 100644 --- a/src/js/node/events.ts +++ b/src/js/node/events.ts @@ -64,7 +64,7 @@ function EventEmitter(opts) { if (opts?.captureRejections) { // TODO: make validator functions return the validated value instead of validating and then coercing an extra time validateBoolean(opts.captureRejections, "options.captureRejections"); - this[kCapture] = Boolean(opts.captureRejections); + this[kCapture] = !!opts.captureRejections; this.emit = emitWithRejectionCapture; } else { this[kCapture] = EventEmitterPrototype[kCapture]; @@ -107,10 +107,10 @@ function emitError(emitter, args) { } } - let er; + let er: Error | undefined; if (args.length > 0) er = args[0]; - if (er instanceof Error) { + if (Error.isError(er)) { throw er; // Unhandled 'error' event } @@ -122,7 +122,7 @@ function emitError(emitter, args) { } // At least give some kind of context to the user - const err = $ERR_UNHANDLED_ERROR(stringifiedEr); + const err = $ERR_UNHANDLED_ERROR(stringifiedEr) as Error & { context: unknown }; err.context = er; throw err; // Unhandled 'error' event } diff --git a/src/js/node/fs.promises.ts b/src/js/node/fs.promises.ts index 6910a28852..4978a48b38 100644 --- a/src/js/node/fs.promises.ts +++ b/src/js/node/fs.promises.ts @@ -1,7 +1,7 @@ // Hardcoded module "node:fs/promises" const types = require("node:util/types"); const EventEmitter = require("node:events"); -const fs = $zig("node_fs_binding.zig", "createBinding"); +const fs = $zig("node_fs_binding.zig", "createBinding") as $ZigGeneratedClasses.NodeJSFS; const { glob } = require("internal/fs/glob"); const constants = $processBindingConstants.fs; @@ -139,7 +139,7 @@ const exports = { exists: async function exists() { try { return await fs.exists.$apply(fs, arguments); - } catch (e) { + } catch { return false; } }, @@ -413,7 +413,7 @@ function asyncWrap(fn: any, name: string) { } } - readLines(options = undefined) { + readLines(_options = undefined) { throw new Error("BUN TODO FileHandle.readLines"); } @@ -550,7 +550,7 @@ function asyncWrap(fn: any, name: string) { return this.close(); } - readableWebStream(options = kEmptyObject) { + readableWebStream(_options = kEmptyObject) { const fd = this[kFd]; throwEBADFIfNecessary("readableWebStream", fd); @@ -585,7 +585,7 @@ function asyncWrap(fn: any, name: string) { throw new Error("BUN TODO FileHandle.kTransferList"); } - [kDeserialize]({ handle }) { + [kDeserialize](_) { throw new Error("BUN TODO FileHandle.kDeserialize"); } @@ -681,26 +681,31 @@ async function writeFileAsyncIterator(fdOrPath, iterable, optionsOrEncoding, fla let totalBytesWritten = 0; + let error: Error | undefined; + try { totalBytesWritten = await writeFileAsyncIteratorInner(fdOrPath, iterable, encoding, signal); - } finally { - if (mustClose) { + } catch (err) { + error = err as Error; + } + + // Handle cleanup outside of try-catch + if (mustClose) { + if (typeof flag === "string" && !flag.includes("a")) { try { - if (typeof flag === "string" && !flag.includes("a")) { - await fs.ftruncate(fdOrPath, totalBytesWritten); - } - } finally { - await fs.close(fdOrPath); - // abort signal shadows other errors - if (signal?.aborted) { - throw signal.reason; - } - } - } else { - // abort signal shadows other errors - if (signal?.aborted) { - throw signal.reason; - } + await fs.ftruncate(fdOrPath, totalBytesWritten); + } catch {} } + + await fs.close(fdOrPath); + } + + // Abort signal shadows other errors + if (signal?.aborted) { + error = signal.reason; + } + + if (error) { + throw error; } } diff --git a/src/js/node/fs.ts b/src/js/node/fs.ts index a7fa2f0905..f0aedf128d 100644 --- a/src/js/node/fs.ts +++ b/src/js/node/fs.ts @@ -207,7 +207,7 @@ var access = function access(path, mode, callback) { existed => callback(existed), _ => callback(false), ); - } catch (e) { + } catch { callback(false); } }, @@ -528,25 +528,25 @@ var access = function access(path, mode, callback) { existsSync = function existsSync() { try { return fs.existsSync.$apply(fs, arguments); - } catch (e) { + } catch { return false; } }, - chownSync = fs.chownSync.bind(fs), - chmodSync = fs.chmodSync.bind(fs), - fchmodSync = fs.fchmodSync.bind(fs), - fchownSync = fs.fchownSync.bind(fs), - fstatSync = fs.fstatSync.bind(fs), - fsyncSync = fs.fsyncSync.bind(fs), - ftruncateSync = fs.ftruncateSync.bind(fs), - futimesSync = fs.futimesSync.bind(fs), + chownSync = fs.chownSync.bind(fs) as unknown as typeof import("node:fs").chownSync, + chmodSync = fs.chmodSync.bind(fs) as unknown as typeof import("node:fs").chmodSync, + fchmodSync = fs.fchmodSync.bind(fs) as unknown as typeof import("node:fs").fchmodSync, + fchownSync = fs.fchownSync.bind(fs) as unknown as typeof import("node:fs").fchownSync, + fstatSync = fs.fstatSync.bind(fs) as unknown as typeof import("node:fs").fstatSync, + fsyncSync = fs.fsyncSync.bind(fs) as unknown as typeof import("node:fs").fsyncSync, + ftruncateSync = fs.ftruncateSync.bind(fs) as unknown as typeof import("node:fs").ftruncateSync, + futimesSync = fs.futimesSync.bind(fs) as unknown as typeof import("node:fs").futimesSync, lchmodSync = constants.O_SYMLINK !== undefined ? fs.lchmodSync.bind(fs) : undefined, // lchmod is only available on macOS - lchownSync = fs.lchownSync.bind(fs), - linkSync = fs.linkSync.bind(fs), - lstatSync = fs.lstatSync.bind(fs), - mkdirSync = fs.mkdirSync.bind(fs), - mkdtempSync = fs.mkdtempSync.bind(fs), - openSync = fs.openSync.bind(fs), + lchownSync = fs.lchownSync.bind(fs) as unknown as typeof import("node:fs").lchownSync, + linkSync = fs.linkSync.bind(fs) as unknown as typeof import("node:fs").linkSync, + lstatSync = fs.lstatSync.bind(fs) as unknown as typeof import("node:fs").lstatSync, + mkdirSync = fs.mkdirSync.bind(fs) as unknown as typeof import("node:fs").mkdirSync, + mkdtempSync = fs.mkdtempSync.bind(fs) as unknown as typeof import("node:fs").mkdtempSync, + openSync = fs.openSync.bind(fs) as unknown as typeof import("node:fs").openSync, readSync = function readSync(fd, buffer, offsetOrOptions, length, position) { let offset = offsetOrOptions; if (arguments.length <= 3 || typeof offsetOrOptions === "object") { @@ -710,9 +710,9 @@ function encodeRealpathResult(result, encoding) { } let assertEncodingForWindows: any = undefined; -const realpathSync = +const realpathSync: typeof import("node:fs").realpathSync = process.platform !== "win32" - ? fs.realpathSync.bind(fs) + ? (fs.realpathSync.bind(fs) as any) : function realpathSync(p, options) { let encoding; if (options) { @@ -813,9 +813,9 @@ const realpathSync = return encodeRealpathResult(p, encoding); }; -const realpath: any = +const realpath: typeof import("node:fs").realpath = process.platform !== "win32" - ? function realpath(p, options, callback) { + ? (function realpath(p, options, callback) { if ($isCallable(options)) { callback = options; options = undefined; @@ -825,8 +825,8 @@ const realpath: any = fs.realpath(p, options, false).then(function (resolvedPath) { callback(null, resolvedPath); }, callback); - } - : function realpath(p, options, callback) { + } as typeof import("node:fs").realpath) + : (function realpath(p, options, callback) { if ($isCallable(options)) { callback = options; options = undefined; @@ -959,7 +959,7 @@ const realpath: any = process.nextTick(LOOP); } } - }; + } as typeof import("node:fs").realpath); realpath.native = function realpath(p, options, callback) { if ($isCallable(options)) { callback = options; @@ -1098,11 +1098,11 @@ class Dir { } async *[Symbol.asyncIterator]() { - let entries = (this.#entries ??= await fs.readdir(this.#path, { + let entries = (this.#entries ??= (await fs.readdir(this.#path, { withFileTypes: true, encoding: this.#options?.encoding, recursive: this.#options?.recursive, - })); + })) as DirentType[]); yield* entries; } } @@ -1247,7 +1247,7 @@ var exports = { }); }, get FileReadStream() { - return (exports.FileReadStream = require("internal/fs/streams").FileReadStream); + return (exports.FileReadStream = require("internal/fs/streams").ReadStream); }, set FileReadStream(value) { Object.defineProperty(exports, "FileReadStream", { @@ -1257,7 +1257,7 @@ var exports = { }); }, get FileWriteStream() { - return (exports.FileWriteStream = require("internal/fs/streams").FileWriteStream); + return (exports.FileWriteStream = require("internal/fs/streams").WriteStream); }, set FileWriteStream(value) { Object.defineProperty(exports, "FileWriteStream", { diff --git a/src/js/node/http.ts b/src/js/node/http.ts index 269b96a130..f6c06cb503 100644 --- a/src/js/node/http.ts +++ b/src/js/node/http.ts @@ -3247,7 +3247,7 @@ function ClientRequest(input, options, cb) { options.host = validateHost(options.hostname, "hostname") || validateHost(options.host, "host") || "localhost"); - const setHost = options.setHost === undefined || Boolean(options.setHost); + const setHost = options.setHost === undefined || !!options.setHost; this[kSocketPath] = options.socketPath; diff --git a/src/js/node/https.ts b/src/js/node/https.ts index 9752228462..f140f45839 100644 --- a/src/js/node/https.ts +++ b/src/js/node/https.ts @@ -2,7 +2,6 @@ const http = require("node:http"); const { urlToHttpOptions } = require("internal/url"); -const ObjectSetPrototypeOf = Object.setPrototypeOf; const ArrayPrototypeShift = Array.prototype.shift; const ObjectAssign = Object.assign; const ArrayPrototypeUnshift = Array.prototype.unshift; diff --git a/src/js/node/net.ts b/src/js/node/net.ts index 280f0d1981..6949318d18 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -32,7 +32,7 @@ const { } = require("internal/net"); const { ExceptionWithHostPort } = require("internal/shared"); import type { SocketListener, SocketHandler } from "bun"; -import type { ServerOpts, Server as ServerType } from "node:net"; +import type { ServerOpts } from "node:net"; const { getTimerDuration } = require("internal/timers"); const { validateFunction, validateNumber, validateAbortSignal } = require("internal/validators"); @@ -45,9 +45,6 @@ var IPv4Reg; const v6Seg = "(?:[0-9a-fA-F]{1,4})"; var IPv6Reg; -const DEFAULT_IPV4_ADDR = "0.0.0.0"; -const DEFAULT_IPV6_ADDR = "::"; - function isIPv4(s): boolean { return (IPv4Reg ??= new RegExp(`^${v4Str}$`)).test(s); } @@ -77,7 +74,6 @@ const { connect: bunConnect } = Bun; var { setTimeout } = globalThis; const bunTlsSymbol = Symbol.for("::buntls::"); -const bunSocketServerHandlers = Symbol.for("::bunsocket_serverhandlers::"); const bunSocketServerConnections = Symbol.for("::bunnetserverconnections::"); const bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"); @@ -116,10 +112,6 @@ function detachSocket(self) { if (!self) self = this; self._handle = null; } -function finishSocket(hasError) { - detachSocket(this); - this.emit("close", hasError); -} function destroyNT(self, err) { self.destroy(err); } @@ -306,7 +298,7 @@ const SocketHandlers: SocketHandler = { binaryType: "buffer", }; -const SocketEmitEndNT = (self, err?) => { +const SocketEmitEndNT = (self, _err?) => { if (!self[kended]) { if (!self.allowHalfOpen) { self.write = writeAfterFIN; @@ -484,8 +476,6 @@ function Socket(options?) { const { socket, signal, - write, - read, allowHalfOpen = false, onread = null, noDelay = false, @@ -689,14 +679,6 @@ Socket.prototype.connect = function connect(...args) { socket, localAddress, localPort, - // TODOs - family, - hints, - lookup, - noDelay, - keepAlive, - keepAliveInitialDelay, - requestCert, rejectUnauthorized, pauseOnConnect, servername, @@ -1413,7 +1395,7 @@ Server.prototype.listen = function listen(port, hostname, onListen) { error.code = "ERR_INVALID_ARG_VALUE"; throw error; } - } else if (!Number.isSafeInteger(port) || port < 0) { + } else if (port === undefined) { port = 0; } @@ -1495,7 +1477,7 @@ Server.prototype[kRealListen] = function ( reusePort, tls, contexts, - onListen, + _onListen, ) { if (path) { this._handle = Bun.listen({ @@ -1697,9 +1679,9 @@ function toNumber(x) { class BlockList { constructor() {} - addSubnet(net, prefix, type) {} + addSubnet(_net, _prefix, _type) {} - check(address, type) { + check(_address, _type) { return false; } } diff --git a/src/js/node/os.ts b/src/js/node/os.ts index 53d6fd5b8f..8c84868295 100644 --- a/src/js/node/os.ts +++ b/src/js/node/os.ts @@ -161,7 +161,7 @@ symbolToStringify(out, "machine"); function symbolToStringify(obj, key) { $assert(obj[key] !== undefined, `Missing ${key}`); - obj[key][Symbol.toPrimitive] = function (hint: string) { + obj[key][Symbol.toPrimitive] = function (_hint: string) { return obj[key](); }; } diff --git a/src/js/node/perf_hooks.ts b/src/js/node/perf_hooks.ts index 45889d4eff..8ec408c4e8 100644 --- a/src/js/node/perf_hooks.ts +++ b/src/js/node/perf_hooks.ts @@ -98,7 +98,7 @@ function createPerformanceNodeTiming() { return object; } -function eventLoopUtilization(utilization1, utilization2) { +function eventLoopUtilization(_utilization1, _utilization2) { return { idle: 0, active: 0, @@ -117,32 +117,32 @@ Object.setPrototypeOf(PerformanceResourceTiming, PerformanceEntry); export default { performance: { - mark(f) { + mark(_) { return performance.mark(...arguments); }, - measure(f) { + measure(_) { return performance.measure(...arguments); }, - clearMarks(f) { + clearMarks(_) { return performance.clearMarks(...arguments); }, - clearMeasures(f) { + clearMeasures(_) { return performance.clearMeasures(...arguments); }, - getEntries(f) { + getEntries(_) { return performance.getEntries(...arguments); }, - getEntriesByName(f) { + getEntriesByName(_) { return performance.getEntriesByName(...arguments); }, - getEntriesByType(f) { + getEntriesByType(_) { return performance.getEntriesByType(...arguments); }, - setResourceTimingBufferSize(f) { + setResourceTimingBufferSize(_) { return performance.setResourceTimingBufferSize(...arguments); }, timeOrigin: performance.timeOrigin, - toJSON(f) { + toJSON(_) { return performance.toJSON(...arguments); }, onresourcetimingbufferfull: performance.onresourcetimingbufferfull, diff --git a/src/js/node/readline.ts b/src/js/node/readline.ts index 2b4d6b4199..ffb92aa9e2 100644 --- a/src/js/node/readline.ts +++ b/src/js/node/readline.ts @@ -84,25 +84,17 @@ const StringPrototypeTrim = String.prototype.trim; const StringPrototypeNormalize = String.prototype.normalize; const NumberIsNaN = Number.isNaN; const NumberIsFinite = Number.isFinite; -const NumberIsInteger = Number.isInteger; -const NumberMAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER; -const NumberMIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER; const MathCeil = Math.ceil; const MathFloor = Math.floor; const MathMax = Math.max; const DateNow = Date.now; -const FunctionPrototype = Function.prototype; const StringPrototype = String.prototype; const StringPrototypeSymbolIterator = StringPrototype[SymbolIterator]; const StringIteratorPrototypeNext = StringPrototypeSymbolIterator.$call("").next; const ObjectSetPrototypeOf = Object.setPrototypeOf; -const ObjectDefineProperty = Object.defineProperty; const ObjectDefineProperties = Object.defineProperties; const ObjectFreeze = Object.freeze; -const ObjectAssign = Object.assign; const ObjectCreate = Object.create; -const ObjectKeys = Object.keys; -const ObjectSeal = Object.seal; var createSafeIterator = (factory, next) => { class SafeIterator { diff --git a/src/js/node/repl.ts b/src/js/node/repl.ts index a7954e70b7..73495f1010 100644 --- a/src/js/node/repl.ts +++ b/src/js/node/repl.ts @@ -3,21 +3,6 @@ // It only exists to make some packages which import this module work. const { throwNotImplemented } = require("internal/shared"); -function REPLServer() { - throwNotImplemented("node:repl REPLServer"); -} - -function Recoverable() { - throwNotImplemented("node:repl Recoverable"); -} - -var REPL_MODE_SLOPPY = 0, - REPL_MODE_STRICT = 1; - -function start() { - throwNotImplemented("node:repl"); -} - const builtinModules = [ "bun", "ffi", diff --git a/src/js/node/test.ts b/src/js/node/test.ts index 9475c35226..3e7101781e 100644 --- a/src/js/node/test.ts +++ b/src/js/node/test.ts @@ -3,165 +3,27 @@ const { jest } = Bun; const { kEmptyObject, throwNotImplemented } = require("internal/shared"); -const Readable = require("internal/streams/readable"); const kDefaultName = ""; const kDefaultFunction = () => {}; const kDefaultOptions = kEmptyObject; -const kDefaultFilePath = callerSourceOrigin(); -function run(...args: unknown[]) { +function run() { throwNotImplemented("run()", 5090, "Use `bun:test` in the interim."); } -function mock(...args: unknown[]) { +function mock() { throwNotImplemented("mock()", 5090, "Use `bun:test` in the interim."); } -/** - * @link https://nodejs.org/api/test.html#class-mockfunctioncontext - */ -class MockFunctionContext { - constructor() { - throwNotImplemented("new MockFunctionContext()", 5090, "Use `bun:test` in the interim."); - } - - get calls() { - throwNotImplemented("calls()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - callCount() { - throwNotImplemented("callCount()", 5090, "Use `bun:test` in the interim."); - return 0; - } - - mockImplementation(fn: Function) { - throwNotImplemented("mockImplementation()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - mockImplementationOnce(fn: Function, onCall?: unknown) { - throwNotImplemented("mockImplementationOnce()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - resetCalls() { - throwNotImplemented("resetCalls()", 5090, "Use `bun:test` in the interim."); - } - - restore() { - throwNotImplemented("restore()", 5090, "Use `bun:test` in the interim."); - } -} - -/** - * @link https://nodejs.org/api/test.html#class-mockmodulecontext - */ -class MockModuleContext { - constructor() { - throwNotImplemented("new MockModuleContext()", 5090, "Use `bun:test` in the interim."); - } - - restore() { - throwNotImplemented("restore()", 5090, "Use `bun:test` in the interim."); - } -} - -/** - * @link https://nodejs.org/api/test.html#class-mocktracker - */ -class MockTracker { - constructor() { - throwNotImplemented("new MockTracker()", 5090, "Use `bun:test` in the interim."); - } - - fn(original: unknown, implementation: unknown, options: unknown) { - throwNotImplemented("fn()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - method(object: unknown, methodName: unknown, implementation: unknown, options: unknown) { - throwNotImplemented("method()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - getter(original: unknown, implementation: unknown, options: unknown) { - throwNotImplemented("getter()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - setter(original: unknown, implementation: unknown, options: unknown) { - throwNotImplemented("setter()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - module(specifier: unknown, options: unknown) { - throwNotImplemented("module()", 5090, "Use `bun:test` in the interim."); - return undefined; - } - - reset() { - throwNotImplemented("reset()", 5090, "Use `bun:test` in the interim."); - } - - restoreAll() { - throwNotImplemented("restoreAll()", 5090, "Use `bun:test` in the interim."); - } -} - -class MockTimers { - constructor() { - throwNotImplemented("new MockTimers()", 5090, "Use `bun:test` in the interim."); - } - - enable(options: unknown) { - throwNotImplemented("enable()", 5090, "Use `bun:test` in the interim."); - } - - reset() { - throwNotImplemented("reset()", 5090, "Use `bun:test` in the interim."); - } - - tick(milliseconds: unknown) { - throwNotImplemented("tick()", 5090, "Use `bun:test` in the interim."); - } - - runAll() { - throwNotImplemented("runAll()", 5090, "Use `bun:test` in the interim."); - } - - setTime(milliseconds: unknown) { - throwNotImplemented("setTime()", 5090, "Use `bun:test` in the interim."); - } - - [Symbol.dispose]() { - this.reset(); - } -} - -/** - * @link https://nodejs.org/api/test.html#class-testsstream - */ -class TestsStream extends Readable { - constructor() { - super(); - throwNotImplemented("new TestsStream()", 5090, "Use `bun:test` in the interim."); - } -} - -function fileSnapshot(value: unknown, path: string, options: { serializers?: Function[] } = kEmptyObject) { +function fileSnapshot(_value: unknown, _path: string, _options: { serializers?: Function[] } = kEmptyObject) { throwNotImplemented("fileSnapshot()", 5090, "Use `bun:test` in the interim."); } -function snapshot(value: unknown, options: { serializers?: Function[] } = kEmptyObject) { +function snapshot(_value: unknown, _options: { serializers?: Function[] } = kEmptyObject) { throwNotImplemented("snapshot()", 5090, "Use `bun:test` in the interim."); } -function register(name: string, fn: Function) { - throwNotImplemented("register()", 5090, "Use `bun:test` in the interim."); -} - const assert = { ...require("node:assert"), fileSnapshot, @@ -184,7 +46,7 @@ class SuiteContext { constructor(name: string | undefined, filePath: string | undefined) { this.#name = name; - this.#filePath = filePath || kDefaultFilePath; + this.#filePath = filePath || Bun.main; } get name(): string { @@ -254,7 +116,7 @@ class TestContext { console.log(message); } - plan(count: number, options: { wait?: boolean } = kEmptyObject) { + plan(_count: number, _options: { wait?: boolean } = kEmptyObject) { throwNotImplemented("plan()", 5090, "Use `bun:test` in the interim."); } @@ -267,43 +129,43 @@ class TestContext { return undefined; } - runOnly(value?: boolean) { + runOnly(_value?: boolean) { throwNotImplemented("runOnly()", 5090, "Use `bun:test` in the interim."); } - skip(message?: string) { + skip(_message?: string) { throwNotImplemented("skip()", 5090, "Use `bun:test` in the interim."); } - todo(message?: string) { + todo(_message?: string) { throwNotImplemented("todo()", 5090, "Use `bun:test` in the interim."); } before(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { beforeAll } = bunTest(this); beforeAll(fn); } after(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { afterAll } = bunTest(this); afterAll(fn); } beforeEach(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { beforeEach } = bunTest(this); beforeEach(fn); } afterEach(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { afterEach } = bunTest(this); afterEach(fn); } - waitFor(condition: unknown, options: { timeout?: number } = kEmptyObject) { + waitFor(_condition: unknown, _options: { timeout?: number } = kEmptyObject) { throwNotImplemented("waitFor()", 5090, "Use `bun:test` in the interim."); } @@ -327,7 +189,7 @@ class TestContext { } describe(arg0: unknown, arg1: unknown, arg2: unknown) { - const { name, fn, options } = createDescribe(arg0, arg1, arg2); + const { name, fn } = createDescribe(arg0, arg1, arg2); if (this.#insideTest) { throwNotImplemented("describe() inside another test()", 5090, "Use `bun:test` in the interim."); @@ -342,28 +204,28 @@ function bunTest(ctx: SuiteContext | TestContext) { return jest(ctx.filePath); } -let ctx = new TestContext(false, undefined, kDefaultFilePath, undefined); +let ctx = new TestContext(false, undefined, Bun.main, undefined); function describe(arg0: unknown, arg1: unknown, arg2: unknown) { - const { name, fn, options } = createDescribe(arg0, arg1, arg2); + const { name, fn } = createDescribe(arg0, arg1, arg2); const { describe } = bunTest(ctx); describe(name, fn); } describe.skip = function (arg0: unknown, arg1: unknown, arg2: unknown) { - const { name, fn, options } = createDescribe(arg0, arg1, arg2); + const { name, fn } = createDescribe(arg0, arg1, arg2); const { describe } = bunTest(ctx); describe.skip(name, fn); }; describe.todo = function (arg0: unknown, arg1: unknown, arg2: unknown) { - const { name, fn, options } = createDescribe(arg0, arg1, arg2); + const { name, fn } = createDescribe(arg0, arg1, arg2); const { describe } = bunTest(ctx); describe.todo(name, fn); }; describe.only = function (arg0: unknown, arg1: unknown, arg2: unknown) { - const { name, fn, options } = createDescribe(arg0, arg1, arg2); + const { name, fn } = createDescribe(arg0, arg1, arg2); const { describe } = bunTest(ctx); describe.only(name, fn); }; @@ -393,59 +255,32 @@ test.only = function (arg0: unknown, arg1: unknown, arg2: unknown) { }; function before(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { beforeAll } = bunTest(ctx); beforeAll(fn); } function after(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { afterAll } = bunTest(ctx); afterAll(fn); } function beforeEach(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { beforeEach } = bunTest(ctx); beforeEach(fn); } function afterEach(arg0: unknown, arg1: unknown) { - const { fn, options } = createHook(arg0, arg1); + const { fn } = createHook(arg0, arg1); const { afterEach } = bunTest(ctx); afterEach(fn); } -function isBuiltinModule(filePath: string) { - return filePath.startsWith("node:") || filePath.startsWith("bun:") || filePath.startsWith("[native code]"); -} - -function callerSourceOrigin(): string { - const error = new Error(); - const originalPrepareStackTrace = Error.prepareStackTrace; - let origin: string | undefined; - Error.prepareStackTrace = (_, stack) => { - origin = stack - .find(s => { - const filePath = s.getFileName(); - if (filePath && !isBuiltinModule(filePath)) { - return filePath; - } - return undefined; - }) - ?.getFileName(); - }; - error.stack; - Error.prepareStackTrace = originalPrepareStackTrace; - if (!origin) { - throw new Error("Failed to get caller source origin"); - } - return origin; -} - function parseTestOptions(arg0: unknown, arg1: unknown, arg2: unknown) { let name: string; - let options: TestOptions; + let options: unknown; let fn: TestFn; if (typeof arg0 === "function") { @@ -478,7 +313,7 @@ function parseTestOptions(arg0: unknown, arg1: unknown, arg2: unknown) { options = kDefaultOptions; } - return { name, options, fn }; + return { name, options: options as TestOptions, fn }; } function createTest(arg0: unknown, arg1: unknown, arg2: unknown) { @@ -594,11 +429,11 @@ type HookOptions = { timeout?: number; }; -function setDefaultSnapshotSerializer(serializers: unknown[]) { +function setDefaultSnapshotSerializer(_serializers: unknown[]) { throwNotImplemented("setDefaultSnapshotSerializer()", 5090, "Use `bun:test` in the interim."); } -function setResolveSnapshotPath(fn: unknown) { +function setResolveSnapshotPath(_fn: unknown) { throwNotImplemented("setResolveSnapshotPath()", 5090, "Use `bun:test` in the interim."); } diff --git a/src/js/node/timers.promises.ts b/src/js/node/timers.promises.ts index 21ccddba1f..eab85e0a23 100644 --- a/src/js/node/timers.promises.ts +++ b/src/js/node/timers.promises.ts @@ -217,7 +217,7 @@ function setIntervalPromise(after = 1, value, options = {}) { return Promise.resolve({}); }, }); - } catch (error) { + } catch { return asyncIterator({ next: function () { clearInterval(interval); diff --git a/src/js/node/timers.ts b/src/js/node/timers.ts index 9edcdc89c7..c72c22a21a 100644 --- a/src/js/node/timers.ts +++ b/src/js/node/timers.ts @@ -30,7 +30,7 @@ export default { throwNotImplemented("'timers.unenroll'"); }, - enroll(timer, msecs) { + enroll(timer, _msecs) { if ($isCallable(timer?.refresh)) { timer.refresh(); return; diff --git a/src/js/node/url.ts b/src/js/node/url.ts index acdf595833..d3b081e1f9 100644 --- a/src/js/node/url.ts +++ b/src/js/node/url.ts @@ -74,8 +74,6 @@ var protocolPattern = /^([a-z0-9.+-]+:)/i, nonHostChars = ["%", "/", "?", ";", "#"].concat(autoEscape), hostEndingChars = ["/", "?", "#"], hostnameMaxLen = 255, - hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, // protocols that can allow "unsafe" and "unwise" chars. unsafeProtocol = { javascript: true, diff --git a/src/js/node/util.ts b/src/js/node/util.ts index 3b66a6bb71..bb7310acb7 100644 --- a/src/js/node/util.ts +++ b/src/js/node/util.ts @@ -22,7 +22,6 @@ function isFunction(value) { const deepEquals = Bun.deepEquals; const isDeepStrictEqual = (a, b) => deepEquals(a, b, true); -var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors; const parseArgs = $newZigFunction("parse_args.zig", "parseArgs", 1); diff --git a/src/js/node/v8.ts b/src/js/node/v8.ts index 082fbfe1dc..eda4cf01dd 100644 --- a/src/js/node/v8.ts +++ b/src/js/node/v8.ts @@ -126,7 +126,7 @@ function getDefaultHeapSnapshotPath() { let fs; -function writeHeapSnapshot(path, options) { +function writeHeapSnapshot(path, _options) { if (path !== undefined) { if (typeof path !== "string") { throw $ERR_INVALID_ARG_TYPE("path", "string", path); diff --git a/src/js/node/wasi.ts b/src/js/node/wasi.ts index 95114861a6..342e082fb3 100644 --- a/src/js/node/wasi.ts +++ b/src/js/node/wasi.ts @@ -1216,7 +1216,7 @@ var require_wasi = __commonJS({ } try { rr = fs.readSync(stats.real, iov, r, length, position); - } catch (_err) {} + } catch {} if (rr == 0) { this.shortPause(); } else { @@ -1437,7 +1437,7 @@ var require_wasi = __commonJS({ path_open: wrap( (dirfd, _dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInheriting, fsFlags, fdPtr) => { try { - const stats = CHECK_FD(dirfd, constants_1.WASI_RIGHT_PATH_OPEN); + CHECK_FD(dirfd, constants_1.WASI_RIGHT_PATH_OPEN); fsRightsBase = BigInt(fsRightsBase); fsRightsInheriting = BigInt(fsRightsInheriting); const read = @@ -1527,7 +1527,7 @@ var require_wasi = __commonJS({ if (write) { try { isDirectory = fs.statSync(full).isDirectory(); - } catch (_err) {} + } catch {} } let realfd; if (!write && isDirectory) { @@ -1616,7 +1616,6 @@ var require_wasi = __commonJS({ let fd = -1; let fd_type = "read"; let fd_timeout_ms = 0; - const startNs = BigInt(bindings.hrtime()); this.refreshMemory(); let last_sin = sin; for (let i = 0; i < nsubscriptions; i += 1) { @@ -1797,7 +1796,7 @@ var require_wasi = __commonJS({ if (real_fd <= 2) { try { return fs.fstatSync(real_fd); - } catch (_) { + } catch { const now = new Date(); return { dev: 0, @@ -1910,7 +1909,7 @@ var require_wasi = __commonJS({ const real = fdInfo[wasi_fd]; try { this.fstatSync(real); - } catch (_err) { + } catch { console.log("discarding ", { wasi_fd, real }); continue; } diff --git a/src/js/node/zlib.ts b/src/js/node/zlib.ts index 34235ac71c..9b966dbce2 100644 --- a/src/js/node/zlib.ts +++ b/src/js/node/zlib.ts @@ -12,9 +12,6 @@ const ArrayPrototypePush = Array.prototype.push; const ObjectDefineProperty = Object.defineProperty; const ObjectDefineProperties = Object.defineProperties; const ObjectFreeze = Object.freeze; -const StringPrototypeStartsWith = String.prototype.startsWith; -const MathMax = Math.max; -const ArrayPrototypeMap = Array.prototype.map; const TypedArrayPrototypeFill = Uint8Array.prototype.fill; const ArrayPrototypeForEach = Array.prototype.forEach; const NumberIsNaN = Number.isNaN; @@ -26,12 +23,7 @@ const kMaxLength = $requireMap.$get("buffer")?.exports.kMaxLength ?? BufferModul const { Transform, finished } = require("node:stream"); const owner_symbol = Symbol("owner_symbol"); -const { - checkRangesOrGetDefault, - validateFunction, - validateUint32, - validateFiniteNumber, -} = require("internal/validators"); +const { checkRangesOrGetDefault, validateFunction, validateFiniteNumber } = require("internal/validators"); const kFlushFlag = Symbol("kFlushFlag"); const kError = Symbol("kError"); @@ -324,7 +316,7 @@ function processChunkSync(self, chunk, flushFlag) { let offset = self._outOffset; const chunkSize = self._chunkSize; - let error; + let error: Error | undefined; self.on("error", function onError(er) { error = er; }); @@ -339,8 +331,14 @@ function processChunkSync(self, chunk, flushFlag) { offset, // out_off availOutBefore, // out_len ); - if (error) throw error; - else if (self[kError]) throw self[kError]; + if (error) { + if (typeof error === "string") { + error = new Error(error); + } else if (!Error.isError(error)) { + error = new Error(String(error)); + } + throw error; + } else if (self[kError]) throw self[kError]; availOutAfter = state[0]; availInAfter = state[1]; diff --git a/src/js/thirdparty/depd.js b/src/js/thirdparty/depd.js deleted file mode 100644 index 9279253ef9..0000000000 --- a/src/js/thirdparty/depd.js +++ /dev/null @@ -1,32 +0,0 @@ -export default function depd(namespace) { - if (!namespace) { - throw new TypeError("argument namespace is required"); - } - function deprecate(message) {} - deprecate._file = void 0; - deprecate._ignored = true; - deprecate._namespace = namespace; - deprecate._traced = false; - deprecate._warned = /* @__PURE__ */ Object.create(null); - deprecate.function = wrapfunction; - deprecate.property = wrapproperty; - return deprecate; -} -function wrapfunction(fn, message) { - if (typeof fn !== "function") { - throw new TypeError("argument fn must be a function"); - } - return fn; -} -function wrapproperty(obj, prop, message) { - if (!obj || (typeof obj !== "object" && typeof obj !== "function")) { - throw new TypeError("argument obj must be object"); - } - var descriptor = Object.getOwnPropertyDescriptor(obj, prop); - if (!descriptor) { - throw new TypeError("must call property on owner object"); - } - if (!descriptor.configurable) { - throw new TypeError("property must be configurable"); - } -} diff --git a/src/js/thirdparty/undici.js b/src/js/thirdparty/undici.js index 74c73772f1..3567f35c41 100644 --- a/src/js/thirdparty/undici.js +++ b/src/js/thirdparty/undici.js @@ -337,7 +337,6 @@ class BalancedPoolMissingUpstreamError extends UndiciError {} class ResponseExceededMaxSizeError extends UndiciError {} class RequestRetryError extends UndiciError {} class SecureProxyConnectionError extends UndiciError {} -class MockNotMatchedError extends UndiciError {} const errors = { AbortError, @@ -437,9 +436,7 @@ const caches = {}; * @param {boolean} [options.allowH2] Whether to allow HTTP/2 connections * @returns {function} A connector function */ -function buildConnector(options = {}) { - const { rejectUnauthorized = true, connectTimeout, maxCachedSessions = 100, allowH2 = false } = options; - +function buildConnector(_options = {}) { /** * @param {Object} options * @param {string} options.hostname @@ -447,7 +444,7 @@ function buildConnector(options = {}) { * @param {string} [options.servername] * @param {AbortSignal} [options.signal] */ - return function connect({ hostname, port, servername, signal }) { + return function connect(_) { notImplemented(); }; } diff --git a/src/js/thirdparty/vercel_fetch.js b/src/js/thirdparty/vercel_fetch.js index 9d9be6c172..6ef03c56b3 100644 --- a/src/js/thirdparty/vercel_fetch.js +++ b/src/js/thirdparty/vercel_fetch.js @@ -16,14 +16,10 @@ export default (wrapper = Bun.fetch) => { try { return await wrapper(url, opts); - } catch (err) { - if (typeof err === "string") { - err = new Error(err); - } - - err.url = url; - err.opts = opts; - throw err; + } catch (error) { + error.url = url; + error.opts = opts; + throw error; } } diff --git a/src/js/thirdparty/ws.js b/src/js/thirdparty/ws.js index 64d1f9a31b..aba6838582 100644 --- a/src/js/thirdparty/ws.js +++ b/src/js/thirdparty/ws.js @@ -8,7 +8,7 @@ const http = require("node:http"); const onceObject = { once: true }; const kBunInternals = Symbol.for("::bunternal::"); const readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"]; -const { kDeprecatedReplySymbol } = require("internal/http"); + const encoder = new TextEncoder(); const eventIds = { open: 1, @@ -945,7 +945,7 @@ class BunWebSocketMocked extends EventEmitter { * not to skip UTF-8 validation for text and close messages * @private */ - setSocket(socket, head, options) { + setSocket(_socket, _head, _options) { throw new Error("Not implemented"); } @@ -999,7 +999,7 @@ class BunWebSocketMocked extends EventEmitter { } // TODO: implement this more proper - addEventListener(type, listener, options) { + addEventListener(type, listener, _options) { if (type === "message") { const l = data => listener({ data }); l.listener = listener; @@ -1325,7 +1325,7 @@ class WebSocketServer extends EventEmitter { if (secWebSocketProtocol !== undefined) { try { protocols = subprotocolParse(secWebSocketProtocol); - } catch (err) { + } catch { const message = "Invalid Sec-WebSocket-Protocol header"; abortHandshakeOrEmitwsClientError(this, req, response, socket, 400, message); return; @@ -1455,7 +1455,7 @@ class Receiver { } } -var createWebSocketStream = ws => { +var createWebSocketStream = _ws => { throw new Error("Not supported yet in Bun"); };