Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
177 commits
Select commit Hold shift + click to select a range
616a338
node:fs, node:dns, node:crypto: route a throw from a callback to unca…
cirospaciari Jul 18, 2026
2f5801c
test: vendor 7 upstream Node v26.3.0 tests that already pass
cirospaciari Jul 19, 2026
8234d7d
test: vendor three more upstream Node v26.3.0 tests
cirospaciari Jul 19, 2026
2dab5b8
test: expose more real internal modules to the vendored node suite
cirospaciari Jul 19, 2026
de4a597
test: vendor test-zlib-zstd-dictionary
cirospaciari Jul 20, 2026
f9a4610
test: remove strays swept in by a bulk add, fix Dir subtest isolation
cirospaciari Jul 20, 2026
3836440
console: move formatTime into internal/util/debuglog
cirospaciari Jul 20, 2026
60fab46
node: DEP0192/DEP0111/DEP0119 warnings and cpu-prof CLI parity
cirospaciari Jul 20, 2026
5442bd9
node:v8: heap statistics shape, cachedDataVersionTag, ERR_NOT_BUILDIN…
cirospaciari Jul 20, 2026
dfca237
node: --heap-prof CLI parity
cirospaciari Jul 20, 2026
ac412e4
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 20, 2026
a3e2c04
node:url and harness: four small compat clusters
cirospaciari Jul 20, 2026
70c8546
node compat: start up from a deleted working directory
cirospaciari Jul 20, 2026
5c544d8
node compat: process.cwd() throws ENOENT after the cwd is removed
cirospaciari Jul 20, 2026
12c23e7
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 20, 2026
f720339
node compat: module-resolution errors match node's shape
cirospaciari Jul 20, 2026
cf8ac6f
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 20, 2026
2a0e723
Merge remote-tracking branch 'origin/claude/heap-prof-cli-parity' int…
cirospaciari Jul 20, 2026
b512b57
Merge remote-tracking branch 'origin/claude/node-v8-small-gaps' into …
cirospaciari Jul 20, 2026
a80a174
Merge remote-tracking branch 'origin/claude/module-not-found-shape' i…
cirospaciari Jul 20, 2026
c59dbe3
Merge remote-tracking branch 'origin/claude/process-cwd-warn' into st…
cirospaciari Jul 20, 2026
6b4d9b6
Merge remote-tracking branch 'origin/claude/node-v26-unclaimed-freewi…
cirospaciari Jul 20, 2026
ff950bf
Fix lint and clippy errors
cirospaciari Jul 20, 2026
04ef27a
node:assert: the Assert class, and node-correct isDeepStrictEqual
cirospaciari Jul 20, 2026
701cc11
Merge remote-tracking branch 'origin/claude/assert-class-deepequal' i…
cirospaciari Jul 20, 2026
f7ecaab
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 20, 2026
0f7d0de
Remove stray test output file
cirospaciari Jul 20, 2026
7f6e602
process: latch DEP0111/DEP0119 warnings per thread, keep debuglog pri…
cirospaciari Jul 20, 2026
084afdc
Fix lint errors in merged assert code
cirospaciari Jul 20, 2026
4021c78
resolve: classify ESM specifiers host-agnostically in node error shaping
cirospaciari Jul 20, 2026
10857f8
Fix stream/iter bytes() returning Buffer, restore upstream test expec…
cirospaciari Jul 20, 2026
a1be861
stream/iter: emulate Node's Buffer pool split in concatBytes; gate ad…
cirospaciari Jul 20, 2026
8aabd9c
test: hold back test-gc-net-timeout until GC delivery timing is reliable
cirospaciari Jul 20, 2026
f9616df
cli: support node's -pe alias
cirospaciari Jul 17, 2026
088e964
cpu profiler: clamp the sampling interval to a usable range
cirospaciari Jul 21, 2026
60d6058
test: vendor test-stdout-close-catch
cirospaciari Jul 21, 2026
82c15b0
Merge origin/main into claude/callback-throw-uncaught
cirospaciari Jul 21, 2026
aef588d
module: implement Node's on-disk compile cache (NODE_COMPILE_CACHE, e…
cirospaciari Jul 21, 2026
030ad4e
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 21, 2026
0ce58c0
compile cache: satisfy clippy's collection, string, and pointer rules
cirospaciari Jul 21, 2026
28a61f2
module: support portable compile cache (NODE_COMPILE_CACHE_PORTABLE, …
cirospaciari Jul 21, 2026
4a1adaa
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 21, 2026
fb9d0f1
compile cache: log relative paths via BStr instead of from_utf8_lossy
cirospaciari Jul 21, 2026
f58d246
test: hold back test-stdout-close-catch until Windows errno mapping i…
cirospaciari Jul 21, 2026
ad15ed6
watch: add --watch-kill-signal, run kill-signal handlers before reloa…
cirospaciari Jul 21, 2026
e233e93
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 21, 2026
05f0d52
cli: display unknown signal names via BStr
cirospaciari Jul 21, 2026
a46fdd9
test: vendor 6 upstream tests that pass after the batch's fixes
cirospaciari Jul 21, 2026
1ff9ae8
async_hooks: deliver createHook lifecycle events for ticks, timers, a…
cirospaciari Jul 21, 2026
6bb13c3
node:fs: emit FSREQCALLBACK async_hooks events for callback-based fs …
cirospaciari Jul 21, 2026
8edc8a7
async_hooks: let timer emit callers own the exception check
cirospaciari Jul 21, 2026
0255ad4
process: fix v8_enable_i18n_support config key typo
cirospaciari Jul 22, 2026
75d3b84
Revert "process: fix v8_enable_i18n_support config key typo"
cirospaciari Jul 22, 2026
0c0d72a
node: expose internal/util helpers to vendored tests (+7 internal-uti…
cirospaciari Jul 22, 2026
d10e487
internal-for-testing: read the WeakReference keepalive in get()
cirospaciari Jul 22, 2026
ed09e02
process: fix v8_enable_i18n_support config key typo and the Intl test…
cirospaciari Jul 22, 2026
93cc9fc
lint: read conditionally-checked properties into locals
cirospaciari Jul 22, 2026
1a351b4
Merge origin/main into claude/callback-throw-uncaught
cirospaciari Jul 22, 2026
be6d609
event loop: wait for in-flight work-pool posters before the shutdown …
cirospaciari Jul 22, 2026
316657e
node: expose more internals to vendored tests (+20 node test files)
cirospaciari Jul 22, 2026
eef7c98
lint: split the stdio fd branches so the property is read once [allow…
cirospaciari Jul 22, 2026
4ee9319
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 22, 2026
42a6973
Address review findings: deepEquals node parity, tamper resistance, h…
cirospaciari Jul 22, 2026
e6884ca
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 22, 2026
f144512
clap: restrict short-alias rewrites to flag-shaped tokens
cirospaciari Jul 22, 2026
cefcacf
url: support the windows option in fileURLToPath
cirospaciari Jul 22, 2026
73bb684
watch: process.exit() in a kill-signal handler must not return to JS
cirospaciari Jul 22, 2026
f5c3586
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 22, 2026
3727840
style: hoist inline callbacks and cite the mirrored node sources
cirospaciari Jul 23, 2026
f1b2ffb
Address review: at-exit cache flush, windows watch signal, util arity…
cirospaciari Jul 23, 2026
769d085
url: apply the Unicode 16 IdnaMappingTable delta before ICU IDNA
cirospaciari Jul 23, 2026
2cb10f0
Merge origin/main into claude/callback-throw-uncaught
cirospaciari Jul 23, 2026
791d81c
assert,module: close review findings on map double-matching and built…
cirospaciari Jul 23, 2026
160870f
lint: drop the now-unused SafeMapPrototypeGet capture [allow size]
cirospaciari Jul 23, 2026
46bd974
module: don't latch the compile-cache exit persist on a non-fatal sel…
cirospaciari Jul 23, 2026
ed2d000
util: isDeepStrictEqual's skipPrototype third argument is public API …
cirospaciari Jul 23, 2026
e67ac08
test: harden the watch kill-signal exit test
cirospaciari Jul 23, 2026
f0717f5
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
2dee4f3
test: realign require-resolve fixture with node's module-not-found wo…
cirospaciari Jul 23, 2026
d9c6c3d
repl: stop echoing and redrawing when stdio is not a TTY
cirospaciari Jul 23, 2026
078b732
module: resolve builtins and validate paths natively in require.resolve
cirospaciari Jul 23, 2026
9c923a6
assert: native URL brand check and typed-array partial containment
cirospaciari Jul 23, 2026
3af6024
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
fd379f0
deepEquals: own-property slot reads, span comparisons, single typed-a…
cirospaciari Jul 23, 2026
d140728
util: node-exact string width and VT stripping; delete the JS width port
cirospaciari Jul 23, 2026
da36af3
assert: move the partialDeepStrictEqual comparison fully to native
cirospaciari Jul 23, 2026
392366f
address review: restore real heap snapshots, dedupe diagnostics, simd…
cirospaciari Jul 23, 2026
e2ee7d4
address review: typed-array partial props, sticky-signal map cleanup,…
cirospaciari Jul 23, 2026
8229fa2
test: remove three vendored node tests bun cannot pass yet
cirospaciari Jul 23, 2026
e6b1d63
deepEquals: reject non-enumerable matches in typed-array own-props; f…
cirospaciari Jul 23, 2026
3a7e7aa
Merge origin/main into claude/callback-throw-uncaught
cirospaciari Jul 23, 2026
311de80
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
421f4c7
assert: node-exact set items and Date/RegExp semantics in the native …
cirospaciari Jul 23, 2026
5e392de
assert: cycle-guard the Set arm of the native partial comparator
cirospaciari Jul 23, 2026
800094b
signals: map SignalCode to real Windows numbers, not Linux discriminants
cirospaciari Jul 23, 2026
7739595
test harness: merge native internal/* entries with the vendored ports
cirospaciari Jul 23, 2026
cceb8f7
assert: boxed primitives compare their internal value in the native p…
cirospaciari Jul 23, 2026
f3a0905
deepEquals: throw node's TypeError for detached DataViews on the node…
cirospaciari Jul 23, 2026
681dbfd
compile cache: drop the STATE lock during bytecode generation
cirospaciari Jul 23, 2026
9d4b9b3
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
4299728
test binding: expose getErrorMessage on the uv internalBinding
cirospaciari Jul 23, 2026
07d4b0a
test: remove test-whatwg-url-toascii until the Unicode 16 host-parsin…
cirospaciari Jul 23, 2026
cd36a54
assert/compile cache: non-index name collection; content-gate the per…
cirospaciari Jul 23, 2026
c840e44
assert: check own properties on Map/Set containers; hoist the width o…
cirospaciari Jul 23, 2026
93db111
followups: native skipPrototype/URL inspect, revert async_hooks, watc…
robobun Jul 23, 2026
e370c0c
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
79a5542
test: clear diff-hygiene grep in vendored fixtures
robobun Jul 23, 2026
af5e076
test: keep advanced-serialization and url-toascii out until #34860 / …
robobun Jul 23, 2026
20ea519
url inspect: satisfy the exception-scope validator; update Bun.inspec…
robobun Jul 23, 2026
ff6e939
ipc: preserve Buffers through advanced serialization
cirospaciari Jul 23, 2026
9f869ac
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
ea50243
review nits: constructorNameOf exception handling, dead code, ANSI wi…
robobun Jul 23, 2026
4fe89b0
url: apply the Unicode 16 IDNA delta to URL constructor and setter hosts
cirospaciari Jul 23, 2026
5dcaceb
dedup: forward ASCIILiteral customInspect to the String overload; dro…
robobun Jul 23, 2026
9c07bb3
watch: move the grace-window poll to a detached timer thread
robobun Jul 23, 2026
e787014
review: DEP0169 latch, comparator exception checks, retired-blob inva…
cirospaciari Jul 23, 2026
76f7da2
v8: preserve Buffers through serialize/deserialize
cirospaciari Jul 23, 2026
755fc98
structuredClone: share SharedArrayBuffer backing stores
cirospaciari Jul 23, 2026
f448594
watch: elect exactly one reload_process winner
cirospaciari Jul 23, 2026
8ea3aad
url: suppress DEP0169 for node_modules callers like node
cirospaciari Jul 23, 2026
9ba7fac
partial KeyObject own-props; gate IDNA delta on special schemes; DEP0…
robobun Jul 23, 2026
3aa00be
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 23, 2026
5ebab22
url: delta pre-pass covers non-canonical special-scheme authorities; …
robobun Jul 23, 2026
6964638
url: CallSite-based isInsideNodeModules for DEP0169 gating
robobun Jul 23, 2026
953fa97
watcher: retry the FileWatcher thread spawn once on transient failure
robobun Jul 24, 2026
3c7b45e
clippy: SAFETY comment on the Watcher::start unsafe; share isInsideNo…
robobun Jul 24, 2026
ab8f9dc
watcher: exit with an error (not a crash report) when FileWatcher thr…
robobun Jul 24, 2026
2f1d212
serialization_buffers: capture Object.*/Set at module load
robobun Jul 24, 2026
01bb898
url: leave same-scheme relative paths untouched by the IDNA delta pre…
robobun Jul 24, 2026
7e9cb77
url: file: only has a host with exactly two slashes; drop redundant D…
robobun Jul 24, 2026
5fe4d07
Merge origin/main into claude/callback-throw-uncaught
robobun Jul 24, 2026
f448798
fix bun_runtime build after merge: SystemError fields are now OwnedSt…
robobun Jul 24, 2026
5db6525
url: bracketed IPv6 hosts skip the IDNA delta pre-pass
robobun Jul 24, 2026
3fb2d5c
Merge origin/main; resolve bindings/inspect/util conflicts; gate v8.d…
robobun Jul 24, 2026
ac5866b
node:fs: match Node's argument-validation error messages
cirospaciari Jul 24, 2026
46fa56b
Match Node's ERR_INVALID_THIS / ERR_MISSING_ARGS wording, and emit tw…
cirospaciari Jul 24, 2026
450022a
Merge main into claude/callback-throw-uncaught
cirospaciari Jul 25, 2026
256f7e5
watch tests: SIGKILL cleanup and a self-limiting wedge fixture
cirospaciari Jul 24, 2026
72f6d84
Merge main into claude/callback-throw-uncaught
cirospaciari Jul 25, 2026
6b93d6a
merge: drop duplicated getStringWidth export key
cirospaciari Jul 25, 2026
803231d
repl: route --interactive to the node REPL entry; width test matches …
cirospaciari Jul 25, 2026
601bbd4
review: drop duplicate DEP0192, guard boxed-string own-prop walk, sim…
robobun Jul 25, 2026
65e6776
watch: bound the kill-signal handler grace window so a wedged handler…
robobun Jul 25, 2026
4125a4a
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 25, 2026
c707a53
url: strip tab/LF/CR before locating the scheme in the IDNA delta pre…
robobun Jul 25, 2026
fa27ead
compile-cache: fetch and persist under --watch; reset signal disposit…
robobun Jul 25, 2026
066766b
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 25, 2026
83f4bf9
bindings: compare DataView own properties via nonIndexOwnPropertiesEq…
robobun Jul 25, 2026
ceb4d49
ci: retrigger
robobun Jul 26, 2026
f36c766
watch: preserve NODE_CHANNEL_FD across the reload execve
robobun Jul 26, 2026
07b0c72
[autofix.ci] apply automated fixes
autofix-ci[bot] Jul 26, 2026
17a268d
review: keep inherited SIG_IGN across reload, drop duplicate --intera…
robobun Jul 26, 2026
c0e2643
url: bound the IDNA delta span to the host so an ignored-class code p…
robobun Jul 26, 2026
b4e7a1f
c-bindings: leave JSC's RT signal and SIGSEGV/SIGBUS for execve to re…
robobun Jul 26, 2026
54cbc6e
assert: add partialDeepStrictEqual to kReadableOperator so its failur…
robobun Jul 26, 2026
c5f729f
NodeUtilTypes: align materialize lambda exception check with sibling;…
robobun Jul 26, 2026
9609332
bindings: skip the symbol-only array pass under checkPrototypes; boun…
robobun Jul 26, 2026
32b5499
compile-cache: gate persist-path display_name/format! allocations on …
robobun Jul 26, 2026
3e0523e
watch: run the pre-execve IPC/signal prep on every POSIX target
robobun Jul 26, 2026
0682b73
url: keep an empty-but-present ?/# marker on the url.format slow path
robobun Jul 26, 2026
bb0c74d
Merge origin/main into claude/callback-throw-uncaught
robobun Jul 28, 2026
af95b68
Merge origin/main into claude/callback-throw-uncaught
robobun Aug 3, 2026
075d547
merge: fix post-merge visibility and rename fallout
robobun Aug 3, 2026
48f0c16
ProcessBindingUV: use default inline capacity so spreading the bindin…
robobun Aug 3, 2026
5529375
shared: capture Error.captureStackTrace at module load and catch tamp…
robobun Aug 3, 2026
5afa23a
crypto: revert pbkdf2 then-handlers to inline arrows
robobun Aug 3, 2026
276e176
Merge remote-tracking branch 'origin/main' into claude/callback-throw…
robobun Aug 3, 2026
3961f52
merge: fix bun_jsc::cpp path in ipc.rs; skip sigThreadSuspendResume (…
robobun Aug 3, 2026
28bb9eb
Merge remote-tracking branch 'origin/claude/callback-throw-uncaught' …
robobun Aug 3, 2026
53ca0e7
shared: move the Error.stackTraceLimit/prepareStackTrace reads inside…
robobun Aug 3, 2026
1bf82f5
trim comments to <=3 lines, cite spec/node source
robobun Aug 3, 2026
e6dab2e
trim comments to <=3 lines, cite spec/node source
robobun Aug 3, 2026
5006828
shared: wrap the isInsideNodeModules frame loop in try/catch so a poi…
robobun Aug 3, 2026
7c59080
url: ERR_INVALID_URL carries error.base when base argument given
robobun Aug 4, 2026
d829edc
Merge remote-tracking branch 'origin/main' into claude/callback-throw…
robobun Aug 4, 2026
5039323
Merge remote-tracking branch 'origin/claude/callback-throw-uncaught' …
robobun Aug 4, 2026
85f06dd
Merge branch 'main' into claude/node-v26-gaps-wave2
robobun Aug 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/js/internal/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,29 @@ function getValidatedFsPath(p: any, propName: string = "path") {
throw $ERR_INVALID_ARG_TYPE(propName, ["string", "Buffer", "URL"], p);
}

// One-shot latch: node:fs and node:fs/promises share it, so it lives here
// alongside the other helpers both modules pull from internal/fs/utils.
var nonPortableTemplateWarn = true;

// https://github.com/nodejs/node/blob/v26.3.0/lib/internal/fs/utils.js#L883-L893
// mkdtemp() templates ending in X are handled inconsistently across platforms.
function warnOnNonPortableTemplate(template: any) {
if (
nonPortableTemplateWarn &&
((typeof template === "string" && template.endsWith("X")) ||
(typeof template !== "string" && template?.at?.(-1) === 0x58))
) {
nonPortableTemplateWarn = false;
process.emitWarning(
"mkdtemp() templates ending with X are not portable. For details see: https://nodejs.org/api/fs.html",
);
}
}

hideFromStack(validateLinkHeaderValue);
hideFromStack(validateString, validateFunction, validateBoolean);
hideFromStack(getValidatedPath, getValidatedFsPath, throwIfNullBytesInFileName);
hideFromStack(warnOnNonPortableTemplate);

export default {
/** (value, name) */
Expand Down Expand Up @@ -166,4 +186,5 @@ export default {
getValidatedFsPath,
/** `(filename)` */
throwIfNullBytesInFileName,
warnOnNonPortableTemplate,
};
7 changes: 6 additions & 1 deletion src/js/node/fs.promises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
validateObject,
validateAbortSignal,
validateEncoding,
warnOnNonPortableTemplate,
} = require("internal/validators");

const constants = $processBindingConstants.fs;
Expand Down Expand Up @@ -283,8 +284,12 @@ const exports = {
link: asyncWrap(fs.link, "link"),
lstat: asyncWrap(fs.lstat, "lstat"),
mkdir: asyncWrap(fs.mkdir, "mkdir"),
mkdtemp: asyncWrap(fs.mkdtemp, "mkdtemp"),
mkdtemp: async function mkdtemp(prefix, options) {
warnOnNonPortableTemplate(prefix);
return fs.mkdtemp(prefix, options);
},
mkdtempDisposable: async function mkdtempDisposable(prefix, options) {
warnOnNonPortableTemplate(prefix);
const path = await fs.mkdtemp(prefix, options);
// Stash the full path in case of process.chdir()
const fullPath = require("node:path").resolve(path);
Expand Down
28 changes: 25 additions & 3 deletions src/js/node/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
validateEncoding,
getValidatedPath,
throwIfNullBytesInFileName,
warnOnNonPortableTemplate,
} = require("internal/validators");

const kEmptyObject = Object.freeze(Object.create(null));
Expand All @@ -31,6 +32,9 @@ function wrapFsCallback(callback) {
return guardCallback(callback);
}

// One-shot latch for the DEP0187 warning node:fs emits at most once per process.
var showExistsDeprecation = true;

// Validates and returns the wrapped callback.
// Callers must use the return value, not the argument.
function ensureCallback(callback) {
Expand Down Expand Up @@ -216,6 +220,7 @@ var access = function access(path, mode, callback) {
}

callback = ensureCallback(callback);
warnOnNonPortableTemplate(prefix);

fs.mkdtemp(prefix, options).then(function (folder) {
callback(null, folder);
Expand Down Expand Up @@ -465,8 +470,22 @@ var access = function access(path, mode, callback) {
closeSync = fs.closeSync.bind(fs),
copyFileSync = fs.copyFileSync.bind(fs),
// This behavior - never throwing -- matches Node.js behavior.
// https://github.com/nodejs/node/blob/c82f3c9e80f0eeec4ae5b7aedd1183127abda4ad/lib/fs.js#L275C1-L295C1
existsSync = function existsSync(_path: string) {
// https://github.com/nodejs/node/blob/v26.3.0/lib/fs.js#L273-L287
existsSync = function existsSync(path: string) {
// Node's getValidatedPath accepts only a string, a Uint8Array, or a URL;
// anything else is the ERR_INVALID_ARG_TYPE that DEP0187 warns about once
// before existsSync swallows it and answers false.
if (typeof path !== "string" && !$isTypedArrayView(path) && !(path instanceof URL)) {
if (showExistsDeprecation) {
showExistsDeprecation = false;
process.emitWarning(
"Passing invalid argument types to fs.existsSync is deprecated",
"DeprecationWarning",
"DEP0187",
);
}
return false;
}
try {
return fs.existsSync.$apply(fs, arguments);
} catch {
Expand All @@ -486,7 +505,10 @@ var access = function access(path, mode, callback) {
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,
mkdtempSync = function mkdtempSync(prefix, options) {
warnOnNonPortableTemplate(prefix);
return fs.mkdtempSync(prefix, options);
} as unknown as typeof import("node:fs").mkdtempSync,
mkdtempDisposableSync = function mkdtempDisposableSync(prefix, options) {
const path = mkdtempSync(prefix, options);
// Stash the full path in case of process.chdir()
Expand Down
6 changes: 5 additions & 1 deletion src/js/node/zlib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,11 @@ function zlibBufferSync(engine, buffer) {
if (isAnyArrayBuffer(buffer)) {
buffer = Buffer.from(buffer);
} else {
throw $ERR_INVALID_ARG_TYPE("buffer", "string, Buffer, TypedArray, DataView, or ArrayBuffer", buffer);
throw $ERR_INVALID_ARG_TYPE(
"buffer",
"string or an instance of Buffer, TypedArray, DataView, or ArrayBuffer",
buffer,
);
}
}
buffer = processChunkSync(engine, buffer, engine._finishFlushFlag);
Expand Down
16 changes: 11 additions & 5 deletions src/jsc/bindings/JSDOMExceptionHandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,26 +269,32 @@ JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::JSGlobalObject& lexica
return createRejectedPromiseWithTypeError(lexicalGlobalObject, JSC::makeDOMAttributeGetterTypeErrorMessage(classInfo->className, String(attributeName.uid())), RejectedPromiseWithTypeErrorCause::NativeGetter);
}

String makeThisTypeErrorMessage(ASCIILiteral interfaceName, ASCIILiteral functionName)
// Node words every ERR_INVALID_THIS the same way regardless of which member
// was called: `Value of "this" must be of type <interface>`.
// https://github.com/nodejs/node/blob/v26.3.0/lib/internal/errors.js
String makeThisTypeErrorMessage(ASCIILiteral interfaceName)
{
return makeString("Can only call "_s, interfaceName, '.', functionName, " on instances of "_s, interfaceName);
return makeString("Value of \"this\" must be of type "_s, interfaceName);
}

EncodedJSValue throwThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral interfaceName, ASCIILiteral attributeName)
{
scope.throwException(&lexicalGlobalObject, Bun::createInvalidThisError(&lexicalGlobalObject, makeThisTypeErrorMessage(interfaceName, attributeName)));
UNUSED_PARAM(attributeName);
scope.throwException(&lexicalGlobalObject, Bun::createInvalidThisError(&lexicalGlobalObject, makeThisTypeErrorMessage(interfaceName)));
return {};
}

JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, ASCIILiteral interfaceName, ASCIILiteral methodName)
{
promise.reject(ExceptionCode::InvalidThisError, makeThisTypeErrorMessage(interfaceName, methodName));
UNUSED_PARAM(methodName);
promise.reject(ExceptionCode::InvalidThisError, makeThisTypeErrorMessage(interfaceName));
return JSValue::encode(jsUndefined());
}

JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, ASCIILiteral interfaceName, ASCIILiteral methodName)
{
return createRejectedPromiseWithTypeError(lexicalGlobalObject, makeThisTypeErrorMessage(interfaceName, methodName), RejectedPromiseWithTypeErrorCause::InvalidThis);
UNUSED_PARAM(methodName);
return createRejectedPromiseWithTypeError(lexicalGlobalObject, makeThisTypeErrorMessage(interfaceName), RejectedPromiseWithTypeErrorCause::InvalidThis);
}

void throwDataCloneError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope)
Expand Down
2 changes: 1 addition & 1 deletion src/jsc/bindings/JSDOMExceptionHandling.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ WEBCORE_EXPORT JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObj
WEBCORE_EXPORT JSC::EncodedJSValue throwDictionaryMemberTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral memberName, ASCIILiteral dictionaryName, ASCIILiteral expectedType);
JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral interfaceName);

String makeThisTypeErrorMessage(ASCIILiteral interfaceName, ASCIILiteral functionName);
String makeThisTypeErrorMessage(ASCIILiteral interfaceName);

WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral interfaceName, ASCIILiteral attributeName);

Expand Down
2 changes: 1 addition & 1 deletion src/jsc/bindings/webcore/JSDOMIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMIteratorPrototype<JSWrapper, I

auto iterator = dynamicDowncast<JSDOMIteratorBase<JSWrapper, IteratorTraits>>(callFrame->thisValue());
if (!iterator) {
return Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_INVALID_THIS, "Cannot call next() on a non-Iterator object"_s);
return Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_INVALID_THIS, makeString("Value of \"this\" must be of type "_s, JSWrapper::info()->className, "Iterator"_s));
}

RELEASE_AND_RETURN(scope, JSC::JSValue::encode(iterator->next(*globalObject)));
Expand Down
13 changes: 7 additions & 6 deletions src/jsc/bindings/webcore/JSURLSearchParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "JSDOMIterator.h"
#include "JSDOMOperation.h"
#include "JSDOMWrapperCache.h"
#include "ErrorCode.h"
#include <JavaScriptCore/BuiltinNames.h>
#include <JavaScriptCore/FunctionPrototype.h>
#include <JavaScriptCore/HeapAnalyzer.h>
Expand Down Expand Up @@ -388,7 +389,7 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_appendBody(
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
if (callFrame->argumentCount() < 2) [[unlikely]]
return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
return Bun::ERR::MISSING_ARGS(throwScope, lexicalGlobalObject, "The \"name\" and \"value\" arguments must be specified"_s);
EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value());
RETURN_IF_EXCEPTION(throwScope, {});
Expand All @@ -411,7 +412,7 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_deleteBody(
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
if (callFrame->argumentCount() < 1) [[unlikely]]
return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
return Bun::ERR::MISSING_ARGS(throwScope, lexicalGlobalObject, "The \"name\" argument must be specified"_s);
EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value());
RETURN_IF_EXCEPTION(throwScope, {});
Expand Down Expand Up @@ -439,7 +440,7 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_getBody(JSC
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
if (callFrame->argumentCount() < 1) [[unlikely]]
return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
return Bun::ERR::MISSING_ARGS(throwScope, lexicalGlobalObject, "The \"name\" argument must be specified"_s);
EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value());
RETURN_IF_EXCEPTION(throwScope, {});
Expand All @@ -459,7 +460,7 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_getAllBody(
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
if (callFrame->argumentCount() < 1) [[unlikely]]
return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
return Bun::ERR::MISSING_ARGS(throwScope, lexicalGlobalObject, "The \"name\" argument must be specified"_s);
EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value());
RETURN_IF_EXCEPTION(throwScope, {});
Expand All @@ -479,7 +480,7 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_hasBody(JSC
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
if (callFrame->argumentCount() < 1) [[unlikely]]
return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
return Bun::ERR::MISSING_ARGS(throwScope, lexicalGlobalObject, "The \"name\" argument must be specified"_s);
EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value());
RETURN_IF_EXCEPTION(throwScope, {});
Expand Down Expand Up @@ -507,7 +508,7 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_setBody(JSC
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
if (callFrame->argumentCount() < 2) [[unlikely]]
return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
return Bun::ERR::MISSING_ARGS(throwScope, lexicalGlobalObject, "The \"name\" and \"value\" arguments must be specified"_s);
EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value());
RETURN_IF_EXCEPTION(throwScope, {});
Expand Down
60 changes: 39 additions & 21 deletions src/runtime/node/node_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ use bun_jsc::AbortSignalRef;
use super::stat::Stats;
use super::time_like::TimeLike;
use super::types::{
ArgumentsSlice, Dirent, Encoding, FdArgExt as _, FileSystemFlags, FileSystemFlagsKind,
NameTooLong, PathLike, PathLikeExt as _, PathOrFdExt as _, StringObjects, StringOrBuffer,
VectorArrayBuffer,
ArgumentsSlice, BUFFER_EXPECTED_TYPES, Dirent, Encoding, FdArgExt as _, FileSystemFlags,
FileSystemFlagsKind, NameTooLong, PathLike, PathLikeExt as _, PathOrFdExt as _, StringObjects,
StringOrBuffer, VectorArrayBuffer,
};
// Re-exported publicly: `crate::node::fs::PathOrFileDescriptor` is the
// canonical path used by `cli/build_command.rs` et al., and `node_fs::Flavor`
Expand Down Expand Up @@ -2671,9 +2671,7 @@ pub mod args {
fs_args_path_forwarders!(Truncate; path);
impl Truncate {
pub fn from_js(ctx: &JSGlobalObject, arguments: &mut ArgumentsSlice) -> JsResult<Truncate> {
let path = PathOrFileDescriptor::from_js(ctx, arguments)?.ok_or_else(|| {
ctx.throw_invalid_arguments(format_args!("path must be a string or TypedArray"))
})?;
let path = PathOrFileDescriptor::from_js_required(ctx, arguments, "path")?;
let len: u64 = 'brk: {
let Some(len_value) = arguments.next() else {
break 'brk 0;
Expand Down Expand Up @@ -3717,14 +3715,35 @@ pub mod args {
break 'parse;
}
let length = current.to_int64();
let max_len = ((buf_len as u64 - args.offset) as i64).min(i32::MAX as i64);
if length > max_len || length < 0 {
// validateOffsetLengthWrite then validateInt32(length, 'length', 0),
// in that order — each stage words its range differently.
let remaining = (buf_len as u64 - args.offset) as i64;
if length > remaining {
return Err(ctx.throw_range_error(
length as f64,
bun_jsc::RangeErrorOptions {
field_name: b"length",
max: remaining,
..Default::default()
},
));
}
if length < 0 {
return Err(ctx.throw_range_error(
length as f64,
bun_jsc::RangeErrorOptions {
field_name: b"length",
min: 0,
max: max_len,
..Default::default()
},
));
}
if length > i32::MAX as i64 {
return Err(ctx.throw_range_error(
length as f64,
bun_jsc::RangeErrorOptions {
field_name: b"length",
msg: b">= 0 && <= 2147483647",
..Default::default()
},
));
Expand Down Expand Up @@ -3849,7 +3868,11 @@ pub mod args {
0.0
};
let buffer = Buffer::from_js(ctx, buffer_value).ok_or_else(|| {
ctx.throw_invalid_argument_type_value(b"buffer", b"TypedArray", buffer_value)
ctx.throw_invalid_argument_type_value2(
b"buffer",
BUFFER_EXPECTED_TYPES,
buffer_value,
)
})?;

// if (length === 0) {
Expand All @@ -3870,9 +3893,12 @@ pub mod args {

let buf_len = buffer.slice().len();
if buf_len == 0 {
let received = JSGlobalObject::inspect_for_error_message(ctx, buffer_value)?;
return Err(validators::throw_err_invalid_arg_value(
ctx,
format_args!("The argument 'buffer' is empty and cannot be written."),
format_args!(
"The argument 'buffer' is empty and cannot be written. Received {received}"
),
));
}
// validateOffsetLengthRead(offset, length, buffer.byteLength);
Expand Down Expand Up @@ -4052,11 +4078,7 @@ pub mod args {
pub fn from_js(ctx: &JSGlobalObject, arguments: &mut ArgumentsSlice) -> JsResult<ReadFile> {
// `Drop` on `path` covers every
// `?`-propagated JsError below.
let path = PathOrFileDescriptor::from_js(ctx, arguments)?.ok_or_else(|| {
ctx.throw_invalid_arguments(format_args!(
"path must be a string or a file descriptor"
))
})?;
let path = PathOrFileDescriptor::from_js_required(ctx, arguments, "path")?;
let mut encoding = Encoding::Buffer;
let mut flag = FileSystemFlags::R;
let mut abort_signal = scopeguard::guard(None::<AbortSignalRef>, |s| {
Expand Down Expand Up @@ -4150,11 +4172,7 @@ pub mod args {
) -> JsResult<WriteFile> {
// `Drop` on `path` covers every
// `?`-propagated JsError below.
let path = PathOrFileDescriptor::from_js(ctx, arguments)?.ok_or_else(|| {
ctx.throw_invalid_arguments(format_args!(
"path must be a string or a file descriptor"
))
})?;
let path = PathOrFileDescriptor::from_js_required(ctx, arguments, "path")?;
let data_value = arguments
.next_eat()
.ok_or_else(|| ctx.throw_invalid_arguments(format_args!("data is required")))?;
Expand Down
Loading
Loading