@secure-exec/nodejs 0.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +7 -0
  3. package/dist/bindings.d.ts +31 -0
  4. package/dist/bindings.js +67 -0
  5. package/dist/bridge/active-handles.d.ts +22 -0
  6. package/dist/bridge/active-handles.js +112 -0
  7. package/dist/bridge/child-process.d.ts +99 -0
  8. package/dist/bridge/child-process.js +672 -0
  9. package/dist/bridge/dispatch.d.ts +2 -0
  10. package/dist/bridge/dispatch.js +40 -0
  11. package/dist/bridge/fs.d.ts +502 -0
  12. package/dist/bridge/fs.js +3307 -0
  13. package/dist/bridge/index.d.ts +10 -0
  14. package/dist/bridge/index.js +41 -0
  15. package/dist/bridge/module.d.ts +75 -0
  16. package/dist/bridge/module.js +325 -0
  17. package/dist/bridge/network.d.ts +1093 -0
  18. package/dist/bridge/network.js +8651 -0
  19. package/dist/bridge/os.d.ts +13 -0
  20. package/dist/bridge/os.js +256 -0
  21. package/dist/bridge/polyfills.d.ts +9 -0
  22. package/dist/bridge/polyfills.js +67 -0
  23. package/dist/bridge/process.d.ts +121 -0
  24. package/dist/bridge/process.js +1382 -0
  25. package/dist/bridge/whatwg-url.d.ts +67 -0
  26. package/dist/bridge/whatwg-url.js +712 -0
  27. package/dist/bridge-contract.d.ts +774 -0
  28. package/dist/bridge-contract.js +172 -0
  29. package/dist/bridge-handlers.d.ts +199 -0
  30. package/dist/bridge-handlers.js +4263 -0
  31. package/dist/bridge-loader.d.ts +9 -0
  32. package/dist/bridge-loader.js +87 -0
  33. package/dist/bridge-setup.d.ts +1 -0
  34. package/dist/bridge-setup.js +3 -0
  35. package/dist/bridge.js +21652 -0
  36. package/dist/builtin-modules.d.ts +25 -0
  37. package/dist/builtin-modules.js +312 -0
  38. package/dist/default-network-adapter.d.ts +13 -0
  39. package/dist/default-network-adapter.js +351 -0
  40. package/dist/driver.d.ts +87 -0
  41. package/dist/driver.js +191 -0
  42. package/dist/esm-compiler.d.ts +14 -0
  43. package/dist/esm-compiler.js +68 -0
  44. package/dist/execution-driver.d.ts +37 -0
  45. package/dist/execution-driver.js +977 -0
  46. package/dist/host-network-adapter.d.ts +7 -0
  47. package/dist/host-network-adapter.js +279 -0
  48. package/dist/index.d.ts +20 -0
  49. package/dist/index.js +23 -0
  50. package/dist/isolate-bootstrap.d.ts +86 -0
  51. package/dist/isolate-bootstrap.js +125 -0
  52. package/dist/ivm-compat.d.ts +7 -0
  53. package/dist/ivm-compat.js +31 -0
  54. package/dist/kernel-runtime.d.ts +58 -0
  55. package/dist/kernel-runtime.js +535 -0
  56. package/dist/module-access.d.ts +75 -0
  57. package/dist/module-access.js +606 -0
  58. package/dist/module-resolver.d.ts +8 -0
  59. package/dist/module-resolver.js +150 -0
  60. package/dist/os-filesystem.d.ts +42 -0
  61. package/dist/os-filesystem.js +161 -0
  62. package/dist/package-bundler.d.ts +36 -0
  63. package/dist/package-bundler.js +497 -0
  64. package/dist/polyfills.d.ts +17 -0
  65. package/dist/polyfills.js +97 -0
  66. package/dist/worker-adapter.d.ts +21 -0
  67. package/dist/worker-adapter.js +34 -0
  68. package/package.json +123 -0
@@ -0,0 +1,3307 @@
1
+ // fs polyfill module for the sandbox
2
+ // This module runs inside the isolate and provides Node.js fs API compatibility
3
+ // It communicates with the host via the _fs Reference object
4
+ import { Buffer } from "buffer";
5
+ const O_RDONLY = 0;
6
+ const O_WRONLY = 1;
7
+ const O_RDWR = 2;
8
+ const O_CREAT = 64;
9
+ const O_EXCL = 128;
10
+ const O_TRUNC = 512;
11
+ const O_APPEND = 1024;
12
+ // Stats class
13
+ class Stats {
14
+ dev;
15
+ ino;
16
+ mode;
17
+ nlink;
18
+ uid;
19
+ gid;
20
+ rdev;
21
+ size;
22
+ blksize;
23
+ blocks;
24
+ atimeMs;
25
+ mtimeMs;
26
+ ctimeMs;
27
+ birthtimeMs;
28
+ atime;
29
+ mtime;
30
+ ctime;
31
+ birthtime;
32
+ constructor(init) {
33
+ this.dev = init.dev ?? 0;
34
+ this.ino = init.ino ?? 0;
35
+ this.mode = init.mode;
36
+ this.nlink = init.nlink ?? 1;
37
+ this.uid = init.uid ?? 0;
38
+ this.gid = init.gid ?? 0;
39
+ this.rdev = init.rdev ?? 0;
40
+ this.size = init.size;
41
+ this.blksize = init.blksize ?? 4096;
42
+ this.blocks = init.blocks ?? Math.ceil(init.size / 512);
43
+ this.atimeMs = init.atimeMs ?? Date.now();
44
+ this.mtimeMs = init.mtimeMs ?? Date.now();
45
+ this.ctimeMs = init.ctimeMs ?? Date.now();
46
+ this.birthtimeMs = init.birthtimeMs ?? Date.now();
47
+ this.atime = new Date(this.atimeMs);
48
+ this.mtime = new Date(this.mtimeMs);
49
+ this.ctime = new Date(this.ctimeMs);
50
+ this.birthtime = new Date(this.birthtimeMs);
51
+ }
52
+ isFile() {
53
+ return (this.mode & 61440) === 32768;
54
+ }
55
+ isDirectory() {
56
+ return (this.mode & 61440) === 16384;
57
+ }
58
+ isSymbolicLink() {
59
+ return (this.mode & 61440) === 40960;
60
+ }
61
+ isBlockDevice() {
62
+ return false;
63
+ }
64
+ isCharacterDevice() {
65
+ return false;
66
+ }
67
+ isFIFO() {
68
+ return false;
69
+ }
70
+ isSocket() {
71
+ return false;
72
+ }
73
+ }
74
+ // Dirent class for readdir with withFileTypes
75
+ class Dirent {
76
+ name;
77
+ parentPath;
78
+ path; // Deprecated alias for parentPath
79
+ _isDir;
80
+ constructor(name, isDir, parentPath = "") {
81
+ this.name = name;
82
+ this._isDir = isDir;
83
+ this.parentPath = parentPath;
84
+ this.path = parentPath;
85
+ }
86
+ isFile() {
87
+ return !this._isDir;
88
+ }
89
+ isDirectory() {
90
+ return this._isDir;
91
+ }
92
+ isSymbolicLink() {
93
+ return false;
94
+ }
95
+ isBlockDevice() {
96
+ return false;
97
+ }
98
+ isCharacterDevice() {
99
+ return false;
100
+ }
101
+ isFIFO() {
102
+ return false;
103
+ }
104
+ isSocket() {
105
+ return false;
106
+ }
107
+ }
108
+ // Dir class for opendir — async-iterable directory handle
109
+ class Dir {
110
+ path;
111
+ _entries = null;
112
+ _index = 0;
113
+ _closed = false;
114
+ constructor(dirPath) {
115
+ this.path = dirPath;
116
+ }
117
+ _load() {
118
+ if (this._entries === null) {
119
+ this._entries = fs.readdirSync(this.path, { withFileTypes: true });
120
+ }
121
+ return this._entries;
122
+ }
123
+ readSync() {
124
+ if (this._closed)
125
+ throw new Error("Directory handle was closed");
126
+ const entries = this._load();
127
+ if (this._index >= entries.length)
128
+ return null;
129
+ return entries[this._index++];
130
+ }
131
+ async read() {
132
+ return this.readSync();
133
+ }
134
+ closeSync() {
135
+ this._closed = true;
136
+ }
137
+ async close() {
138
+ this.closeSync();
139
+ }
140
+ async *[Symbol.asyncIterator]() {
141
+ const entries = this._load();
142
+ for (const entry of entries) {
143
+ if (this._closed)
144
+ return;
145
+ yield entry;
146
+ }
147
+ this._closed = true;
148
+ }
149
+ }
150
+ const FILE_HANDLE_READ_CHUNK_BYTES = 64 * 1024;
151
+ const FILE_HANDLE_READ_BUFFER_BYTES = 16 * 1024;
152
+ const FILE_HANDLE_MAX_READ_BYTES = 2 ** 31 - 1;
153
+ function createAbortError(reason) {
154
+ const error = new Error("The operation was aborted");
155
+ error.name = "AbortError";
156
+ error.code = "ABORT_ERR";
157
+ if (reason !== undefined) {
158
+ error.cause = reason;
159
+ }
160
+ return error;
161
+ }
162
+ function validateAbortSignal(signal) {
163
+ if (signal === undefined) {
164
+ return undefined;
165
+ }
166
+ if (signal === null ||
167
+ typeof signal !== "object" ||
168
+ typeof signal.aborted !== "boolean" ||
169
+ typeof signal.addEventListener !== "function" ||
170
+ typeof signal.removeEventListener !== "function") {
171
+ const error = new TypeError('The "signal" argument must be an instance of AbortSignal');
172
+ error.code = "ERR_INVALID_ARG_TYPE";
173
+ throw error;
174
+ }
175
+ return signal;
176
+ }
177
+ function throwIfAborted(signal) {
178
+ if (signal?.aborted) {
179
+ throw createAbortError(signal.reason);
180
+ }
181
+ }
182
+ function waitForNextTick() {
183
+ return new Promise((resolve) => process.nextTick(resolve));
184
+ }
185
+ function createInternalAssertionError(message) {
186
+ const error = new Error(message);
187
+ error.code = "ERR_INTERNAL_ASSERTION";
188
+ return error;
189
+ }
190
+ function createOutOfRangeError(name, range, received) {
191
+ const error = new RangeError(`The value of "${name}" is out of range. It must be ${range}. Received ${String(received)}`);
192
+ error.code = "ERR_OUT_OF_RANGE";
193
+ return error;
194
+ }
195
+ function formatInvalidArgReceived(actual) {
196
+ if (actual === null) {
197
+ return "Received null";
198
+ }
199
+ if (actual === undefined) {
200
+ return "Received undefined";
201
+ }
202
+ if (typeof actual === "string") {
203
+ return `Received type string ('${actual}')`;
204
+ }
205
+ if (typeof actual === "number") {
206
+ return `Received type number (${String(actual)})`;
207
+ }
208
+ if (typeof actual === "boolean") {
209
+ return `Received type boolean (${String(actual)})`;
210
+ }
211
+ if (typeof actual === "bigint") {
212
+ return `Received type bigint (${actual.toString()}n)`;
213
+ }
214
+ if (typeof actual === "symbol") {
215
+ return `Received type symbol (${String(actual)})`;
216
+ }
217
+ if (typeof actual === "function") {
218
+ return actual.name ? `Received function ${actual.name}` : "Received function";
219
+ }
220
+ if (Array.isArray(actual)) {
221
+ return "Received an instance of Array";
222
+ }
223
+ if (actual && typeof actual === "object") {
224
+ const constructorName = actual.constructor?.name;
225
+ if (constructorName) {
226
+ return `Received an instance of ${constructorName}`;
227
+ }
228
+ }
229
+ return `Received type ${typeof actual} (${String(actual)})`;
230
+ }
231
+ function createInvalidArgTypeError(name, expected, actual) {
232
+ const error = new TypeError(`The "${name}" argument must be ${expected}. ${formatInvalidArgReceived(actual)}`);
233
+ error.code = "ERR_INVALID_ARG_TYPE";
234
+ return error;
235
+ }
236
+ function createInvalidArgValueError(name, message) {
237
+ const error = new TypeError(`The argument '${name}' ${message}`);
238
+ error.code = "ERR_INVALID_ARG_VALUE";
239
+ return error;
240
+ }
241
+ function createInvalidEncodingError(encoding) {
242
+ const printable = typeof encoding === "string"
243
+ ? `'${encoding}'`
244
+ : encoding === undefined
245
+ ? "undefined"
246
+ : encoding === null
247
+ ? "null"
248
+ : String(encoding);
249
+ const error = new TypeError(`The argument 'encoding' is invalid encoding. Received ${printable}`);
250
+ error.code = "ERR_INVALID_ARG_VALUE";
251
+ return error;
252
+ }
253
+ function toUint8ArrayChunk(chunk, encoding) {
254
+ if (typeof chunk === "string") {
255
+ return Buffer.from(chunk, encoding ?? "utf8");
256
+ }
257
+ if (Buffer.isBuffer(chunk)) {
258
+ return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
259
+ }
260
+ if (chunk instanceof Uint8Array) {
261
+ return chunk;
262
+ }
263
+ if (ArrayBuffer.isView(chunk)) {
264
+ return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
265
+ }
266
+ throw createInvalidArgTypeError("data", "a string, Buffer, TypedArray, or DataView", chunk);
267
+ }
268
+ async function* iterateWriteChunks(data, encoding) {
269
+ if (typeof data === "string" || ArrayBuffer.isView(data)) {
270
+ yield toUint8ArrayChunk(data, encoding);
271
+ return;
272
+ }
273
+ if (data && typeof data[Symbol.asyncIterator] === "function") {
274
+ for await (const chunk of data) {
275
+ yield toUint8ArrayChunk(chunk, encoding);
276
+ }
277
+ return;
278
+ }
279
+ if (data && typeof data[Symbol.iterator] === "function") {
280
+ for (const chunk of data) {
281
+ yield toUint8ArrayChunk(chunk, encoding);
282
+ }
283
+ return;
284
+ }
285
+ throw createInvalidArgTypeError("data", "a string, Buffer, TypedArray, DataView, or Iterable", data);
286
+ }
287
+ class FileHandle {
288
+ _fd;
289
+ _closing = false;
290
+ _closed = false;
291
+ _listeners = new Map();
292
+ constructor(fd) {
293
+ this._fd = fd;
294
+ }
295
+ static _assertHandle(handle) {
296
+ if (!(handle instanceof FileHandle)) {
297
+ throw createInternalAssertionError("handle must be an instance of FileHandle");
298
+ }
299
+ return handle;
300
+ }
301
+ _emitCloseOnce() {
302
+ if (this._closed) {
303
+ this._fd = -1;
304
+ this.emit("close");
305
+ return;
306
+ }
307
+ this._closed = true;
308
+ this._fd = -1;
309
+ this.emit("close");
310
+ }
311
+ _resolvePath() {
312
+ if (this._fd < 0) {
313
+ return null;
314
+ }
315
+ return _fdGetPath.applySync(undefined, [this._fd]);
316
+ }
317
+ get fd() {
318
+ return this._fd;
319
+ }
320
+ get closed() {
321
+ return this._closed;
322
+ }
323
+ on(event, listener) {
324
+ const listeners = this._listeners.get(event) ?? [];
325
+ listeners.push(listener);
326
+ this._listeners.set(event, listeners);
327
+ return this;
328
+ }
329
+ once(event, listener) {
330
+ const wrapper = (...args) => {
331
+ this.off(event, wrapper);
332
+ listener(...args);
333
+ };
334
+ wrapper._originalListener = listener;
335
+ return this.on(event, wrapper);
336
+ }
337
+ off(event, listener) {
338
+ const listeners = this._listeners.get(event);
339
+ if (!listeners) {
340
+ return this;
341
+ }
342
+ const index = listeners.findIndex((candidate) => candidate === listener ||
343
+ candidate._originalListener === listener);
344
+ if (index !== -1) {
345
+ listeners.splice(index, 1);
346
+ }
347
+ return this;
348
+ }
349
+ removeListener(event, listener) {
350
+ return this.off(event, listener);
351
+ }
352
+ emit(event, ...args) {
353
+ const listeners = this._listeners.get(event);
354
+ if (!listeners || listeners.length === 0) {
355
+ return false;
356
+ }
357
+ for (const listener of listeners.slice()) {
358
+ listener(...args);
359
+ }
360
+ return true;
361
+ }
362
+ async close() {
363
+ const handle = FileHandle._assertHandle(this);
364
+ if (handle._closing || handle._closed) {
365
+ if (handle._fd < 0) {
366
+ throw createFsError("EBADF", "EBADF: bad file descriptor, close", "close");
367
+ }
368
+ }
369
+ handle._closing = true;
370
+ try {
371
+ fs.closeSync(handle._fd);
372
+ handle._emitCloseOnce();
373
+ }
374
+ finally {
375
+ handle._closing = false;
376
+ }
377
+ }
378
+ async stat() {
379
+ const handle = FileHandle._assertHandle(this);
380
+ return fs.fstatSync(handle.fd);
381
+ }
382
+ async sync() {
383
+ const handle = FileHandle._assertHandle(this);
384
+ fs.fsyncSync(handle.fd);
385
+ }
386
+ async datasync() {
387
+ return this.sync();
388
+ }
389
+ async truncate(len) {
390
+ const handle = FileHandle._assertHandle(this);
391
+ fs.ftruncateSync(handle.fd, len);
392
+ }
393
+ async chmod(mode) {
394
+ const handle = FileHandle._assertHandle(this);
395
+ const path = handle._resolvePath();
396
+ if (!path) {
397
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "chmod");
398
+ }
399
+ fs.chmodSync(path, mode);
400
+ }
401
+ async chown(uid, gid) {
402
+ const handle = FileHandle._assertHandle(this);
403
+ const path = handle._resolvePath();
404
+ if (!path) {
405
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "chown");
406
+ }
407
+ fs.chownSync(path, uid, gid);
408
+ }
409
+ async utimes(atime, mtime) {
410
+ const handle = FileHandle._assertHandle(this);
411
+ const path = handle._resolvePath();
412
+ if (!path) {
413
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "utimes");
414
+ }
415
+ fs.utimesSync(path, atime, mtime);
416
+ }
417
+ async read(buffer, offset, length, position) {
418
+ const handle = FileHandle._assertHandle(this);
419
+ let target = buffer;
420
+ if (target === null) {
421
+ target = Buffer.alloc(FILE_HANDLE_READ_BUFFER_BYTES);
422
+ }
423
+ if (!ArrayBuffer.isView(target)) {
424
+ throw createInvalidArgTypeError("buffer", "an instance of ArrayBufferView", target);
425
+ }
426
+ const readOffset = offset ?? 0;
427
+ const readLength = length ?? (target.byteLength - readOffset);
428
+ const bytesRead = fs.readSync(handle.fd, target, readOffset, readLength, position ?? null);
429
+ return { bytesRead, buffer: target };
430
+ }
431
+ async write(buffer, offsetOrPosition, lengthOrEncoding, position) {
432
+ const handle = FileHandle._assertHandle(this);
433
+ if (typeof buffer === "string") {
434
+ const encoding = typeof lengthOrEncoding === "string" ? lengthOrEncoding : "utf8";
435
+ if (encoding === "hex" && buffer.length % 2 !== 0) {
436
+ throw createInvalidArgValueError("encoding", `is invalid for data of length ${buffer.length}`);
437
+ }
438
+ const bytesWritten = fs.writeSync(handle.fd, Buffer.from(buffer, encoding), 0, undefined, offsetOrPosition ?? null);
439
+ return { bytesWritten, buffer };
440
+ }
441
+ if (!ArrayBuffer.isView(buffer)) {
442
+ throw createInvalidArgTypeError("buffer", "a string, Buffer, TypedArray, or DataView", buffer);
443
+ }
444
+ const offset = offsetOrPosition ?? 0;
445
+ const length = typeof lengthOrEncoding === "number" ? lengthOrEncoding : undefined;
446
+ const bytesWritten = fs.writeSync(handle.fd, buffer, offset, length, position ?? null);
447
+ return { bytesWritten, buffer };
448
+ }
449
+ async readFile(options) {
450
+ const handle = FileHandle._assertHandle(this);
451
+ const normalized = typeof options === "string" ? { encoding: options } : (options ?? undefined);
452
+ const signal = validateAbortSignal(normalized?.signal);
453
+ const encoding = normalized?.encoding ?? undefined;
454
+ const stats = await handle.stat();
455
+ if (stats.size > FILE_HANDLE_MAX_READ_BYTES) {
456
+ const error = new RangeError("File size is greater than 2 GiB");
457
+ error.code = "ERR_FS_FILE_TOO_LARGE";
458
+ throw error;
459
+ }
460
+ await waitForNextTick();
461
+ throwIfAborted(signal);
462
+ const chunks = [];
463
+ let totalLength = 0;
464
+ while (true) {
465
+ throwIfAborted(signal);
466
+ const chunk = Buffer.alloc(FILE_HANDLE_READ_CHUNK_BYTES);
467
+ const { bytesRead } = await handle.read(chunk, 0, chunk.byteLength, null);
468
+ if (bytesRead === 0) {
469
+ break;
470
+ }
471
+ chunks.push(chunk.subarray(0, bytesRead));
472
+ totalLength += bytesRead;
473
+ if (totalLength > FILE_HANDLE_MAX_READ_BYTES) {
474
+ const error = new RangeError("File size is greater than 2 GiB");
475
+ error.code = "ERR_FS_FILE_TOO_LARGE";
476
+ throw error;
477
+ }
478
+ await waitForNextTick();
479
+ }
480
+ const result = Buffer.concat(chunks, totalLength);
481
+ return encoding ? result.toString(encoding) : result;
482
+ }
483
+ async writeFile(data, options) {
484
+ const handle = FileHandle._assertHandle(this);
485
+ const normalized = typeof options === "string" ? { encoding: options } : (options ?? undefined);
486
+ const signal = validateAbortSignal(normalized?.signal);
487
+ const encoding = normalized?.encoding ?? undefined;
488
+ await waitForNextTick();
489
+ throwIfAborted(signal);
490
+ for await (const chunk of iterateWriteChunks(data, encoding)) {
491
+ throwIfAborted(signal);
492
+ await handle.write(chunk, 0, chunk.byteLength, undefined);
493
+ await waitForNextTick();
494
+ }
495
+ }
496
+ async appendFile(data, options) {
497
+ return this.writeFile(data, options);
498
+ }
499
+ createReadStream(options) {
500
+ FileHandle._assertHandle(this);
501
+ return new ReadStream(null, { ...(options ?? {}), fd: this });
502
+ }
503
+ createWriteStream(options) {
504
+ FileHandle._assertHandle(this);
505
+ return new WriteStream(null, { ...(options ?? {}), fd: this });
506
+ }
507
+ }
508
+ function isArrayBufferView(value) {
509
+ return ArrayBuffer.isView(value);
510
+ }
511
+ function createInvalidPropertyTypeError(propertyPath, actual) {
512
+ let received;
513
+ if (actual === null) {
514
+ received = "Received null";
515
+ }
516
+ else if (typeof actual === "string") {
517
+ received = `Received type string ('${actual}')`;
518
+ }
519
+ else {
520
+ received = `Received type ${typeof actual} (${String(actual)})`;
521
+ }
522
+ const error = new TypeError(`The "${propertyPath}" property must be of type function. ${received}`);
523
+ error.code = "ERR_INVALID_ARG_TYPE";
524
+ return error;
525
+ }
526
+ function validateCallback(callback, name = "cb") {
527
+ if (typeof callback !== "function") {
528
+ throw createInvalidArgTypeError(name, "of type function", callback);
529
+ }
530
+ }
531
+ function validateEncodingValue(encoding) {
532
+ if (encoding === undefined || encoding === null) {
533
+ return;
534
+ }
535
+ if (typeof encoding !== "string" || !Buffer.isEncoding(encoding)) {
536
+ throw createInvalidEncodingError(encoding);
537
+ }
538
+ }
539
+ function validateEncodingOption(options) {
540
+ if (typeof options === "string") {
541
+ validateEncodingValue(options);
542
+ return;
543
+ }
544
+ if (options && typeof options === "object" && "encoding" in options) {
545
+ validateEncodingValue(options.encoding);
546
+ }
547
+ }
548
+ function normalizePathLike(path, name = "path") {
549
+ if (typeof path === "string") {
550
+ return path;
551
+ }
552
+ if (Buffer.isBuffer(path)) {
553
+ return path.toString("utf8");
554
+ }
555
+ if (path instanceof URL) {
556
+ if (path.protocol === "file:") {
557
+ return path.pathname;
558
+ }
559
+ throw createInvalidArgTypeError(name, "of type string or an instance of Buffer or URL", path);
560
+ }
561
+ throw createInvalidArgTypeError(name, "of type string or an instance of Buffer or URL", path);
562
+ }
563
+ function tryNormalizeExistsPath(path) {
564
+ try {
565
+ return normalizePathLike(path);
566
+ }
567
+ catch {
568
+ return null;
569
+ }
570
+ }
571
+ function normalizeNumberArgument(name, value, options = {}) {
572
+ const { min = 0, max = 0x7fffffff, allowNegativeOne = false } = options;
573
+ if (typeof value !== "number") {
574
+ throw createInvalidArgTypeError(name, "of type number", value);
575
+ }
576
+ if (!Number.isFinite(value) || !Number.isInteger(value)) {
577
+ throw createOutOfRangeError(name, "an integer", value);
578
+ }
579
+ if ((allowNegativeOne && value === -1) || (value >= min && value <= max)) {
580
+ return value;
581
+ }
582
+ throw createOutOfRangeError(name, `>= ${min} && <= ${max}`, value);
583
+ }
584
+ function normalizeModeArgument(mode, name = "mode") {
585
+ if (typeof mode === "string") {
586
+ if (!/^[0-7]+$/.test(mode)) {
587
+ throw createInvalidArgValueError(name, "must be a 32-bit unsigned integer or an octal string. Received '" + mode + "'");
588
+ }
589
+ return parseInt(mode, 8);
590
+ }
591
+ return normalizeNumberArgument(name, mode, { min: 0, max: 0xffffffff });
592
+ }
593
+ function normalizeOpenModeArgument(mode) {
594
+ if (mode === undefined || mode === null) {
595
+ return undefined;
596
+ }
597
+ return normalizeModeArgument(mode);
598
+ }
599
+ function validateWriteStreamStartOption(options) {
600
+ if (options?.start === undefined) {
601
+ return;
602
+ }
603
+ if (typeof options.start !== "number") {
604
+ throw createInvalidArgTypeError("start", "of type number", options.start);
605
+ }
606
+ if (!Number.isFinite(options.start) || !Number.isInteger(options.start) || options.start < 0) {
607
+ throw createOutOfRangeError("start", ">= 0", options.start);
608
+ }
609
+ }
610
+ function validateBooleanOption(name, value) {
611
+ if (value === undefined) {
612
+ return undefined;
613
+ }
614
+ if (typeof value !== "boolean") {
615
+ throw createInvalidArgTypeError(name, "of type boolean", value);
616
+ }
617
+ return value;
618
+ }
619
+ function validateAbortSignalOption(name, signal) {
620
+ if (signal === undefined) {
621
+ return undefined;
622
+ }
623
+ if (signal === null ||
624
+ typeof signal !== "object" ||
625
+ typeof signal.aborted !== "boolean" ||
626
+ typeof signal.addEventListener !== "function" ||
627
+ typeof signal.removeEventListener !== "function") {
628
+ const error = new TypeError(`The "${name}" property must be an instance of AbortSignal. ${formatInvalidArgReceived(signal)}`);
629
+ error.code = "ERR_INVALID_ARG_TYPE";
630
+ throw error;
631
+ }
632
+ return signal;
633
+ }
634
+ function createUnsupportedWatcherError(api) {
635
+ return new Error(`fs.${api} is not supported in sandbox — use polling`);
636
+ }
637
+ function normalizeWatchOptions(options, allowString) {
638
+ let normalized;
639
+ if (options === undefined || options === null) {
640
+ normalized = {};
641
+ }
642
+ else if (typeof options === "string") {
643
+ if (!allowString) {
644
+ throw createInvalidArgTypeError("options", "of type object", options);
645
+ }
646
+ validateEncodingValue(options);
647
+ normalized = { encoding: options };
648
+ }
649
+ else if (typeof options === "object") {
650
+ normalized = options;
651
+ }
652
+ else {
653
+ throw createInvalidArgTypeError("options", allowString ? "one of type string or object" : "of type object", options);
654
+ }
655
+ validateBooleanOption("options.persistent", normalized.persistent);
656
+ validateBooleanOption("options.recursive", normalized.recursive);
657
+ validateEncodingOption(normalized);
658
+ const signal = validateAbortSignalOption("options.signal", normalized.signal);
659
+ return {
660
+ persistent: normalized.persistent,
661
+ recursive: normalized.recursive,
662
+ encoding: normalized.encoding,
663
+ signal,
664
+ };
665
+ }
666
+ function normalizeWatchArguments(path, optionsOrListener, listener) {
667
+ normalizePathLike(path);
668
+ let options = optionsOrListener;
669
+ let resolvedListener = listener;
670
+ if (typeof optionsOrListener === "function") {
671
+ options = undefined;
672
+ resolvedListener = optionsOrListener;
673
+ }
674
+ if (resolvedListener !== undefined && typeof resolvedListener !== "function") {
675
+ throw createInvalidArgTypeError("listener", "of type function", resolvedListener);
676
+ }
677
+ return normalizeWatchOptions(options, true);
678
+ }
679
+ function normalizeWatchFileArguments(path, optionsOrListener, listener) {
680
+ normalizePathLike(path);
681
+ let options = {};
682
+ let resolvedListener = listener;
683
+ if (typeof optionsOrListener === "function") {
684
+ resolvedListener = optionsOrListener;
685
+ }
686
+ else if (optionsOrListener === undefined || optionsOrListener === null) {
687
+ options = {};
688
+ }
689
+ else if (typeof optionsOrListener === "object") {
690
+ options = optionsOrListener;
691
+ }
692
+ else {
693
+ throw createInvalidArgTypeError("listener", "of type function", optionsOrListener);
694
+ }
695
+ if (typeof resolvedListener !== "function") {
696
+ throw createInvalidArgTypeError("listener", "of type function", resolvedListener);
697
+ }
698
+ if (options.interval !== undefined && typeof options.interval !== "number") {
699
+ throw createInvalidArgTypeError("interval", "of type number", options.interval);
700
+ }
701
+ }
702
+ async function* createUnsupportedPromisesWatchIterator(path, options) {
703
+ const normalized = normalizeWatchOptions(options, false);
704
+ normalizePathLike(path);
705
+ throwIfAborted(normalized.signal);
706
+ throw createUnsupportedWatcherError("promises.watch");
707
+ }
708
+ function isReadWriteOptionsObject(value) {
709
+ return value === null || value === undefined || (typeof value === "object" && !Array.isArray(value));
710
+ }
711
+ function normalizeOptionalPosition(value) {
712
+ if (value === undefined || value === null || value === -1) {
713
+ return null;
714
+ }
715
+ if (typeof value === "bigint") {
716
+ return Number(value);
717
+ }
718
+ if (typeof value !== "number" || !Number.isInteger(value)) {
719
+ throw createInvalidArgTypeError("position", "an integer", value);
720
+ }
721
+ return value;
722
+ }
723
+ function normalizeOffsetLength(bufferByteLength, offsetValue, lengthValue) {
724
+ const offset = offsetValue ?? 0;
725
+ if (typeof offset !== "number" || !Number.isInteger(offset)) {
726
+ throw createInvalidArgTypeError("offset", "an integer", offset);
727
+ }
728
+ if (offset < 0 || offset > bufferByteLength) {
729
+ throw createOutOfRangeError("offset", `>= 0 && <= ${bufferByteLength}`, offset);
730
+ }
731
+ const defaultLength = bufferByteLength - offset;
732
+ const length = lengthValue ?? defaultLength;
733
+ if (typeof length !== "number" || !Number.isInteger(length)) {
734
+ throw createInvalidArgTypeError("length", "an integer", length);
735
+ }
736
+ if (length < 0 || length > 0x7fffffff) {
737
+ throw createOutOfRangeError("length", ">= 0 && <= 2147483647", length);
738
+ }
739
+ if (offset + length > bufferByteLength) {
740
+ throw createOutOfRangeError("length", `>= 0 && <= ${bufferByteLength - offset}`, length);
741
+ }
742
+ return { offset, length };
743
+ }
744
+ function normalizeReadSyncArgs(buffer, offsetOrOptions, length, position) {
745
+ if (!isArrayBufferView(buffer)) {
746
+ throw createInvalidArgTypeError("buffer", "an instance of Buffer, TypedArray, or DataView", buffer);
747
+ }
748
+ if (length === undefined &&
749
+ position === undefined &&
750
+ isReadWriteOptionsObject(offsetOrOptions)) {
751
+ const options = (offsetOrOptions ?? {});
752
+ const { offset, length } = normalizeOffsetLength(buffer.byteLength, options.offset, options.length);
753
+ return {
754
+ buffer,
755
+ offset,
756
+ length,
757
+ position: normalizeOptionalPosition(options.position),
758
+ };
759
+ }
760
+ const { offset, length: normalizedLength } = normalizeOffsetLength(buffer.byteLength, offsetOrOptions, length);
761
+ return {
762
+ buffer,
763
+ offset,
764
+ length: normalizedLength,
765
+ position: normalizeOptionalPosition(position),
766
+ };
767
+ }
768
+ function normalizeWriteSyncArgs(buffer, offsetOrPosition, lengthOrEncoding, position) {
769
+ if (typeof buffer === "string") {
770
+ if (lengthOrEncoding === undefined &&
771
+ position === undefined &&
772
+ isReadWriteOptionsObject(offsetOrPosition)) {
773
+ const options = (offsetOrPosition ?? {});
774
+ const encoding = typeof options.encoding === "string" ? options.encoding : undefined;
775
+ return {
776
+ buffer,
777
+ offset: 0,
778
+ length: Buffer.byteLength(buffer, encoding),
779
+ position: normalizeOptionalPosition(options.position),
780
+ encoding,
781
+ };
782
+ }
783
+ if (offsetOrPosition !== undefined &&
784
+ offsetOrPosition !== null &&
785
+ typeof offsetOrPosition !== "number") {
786
+ throw createInvalidArgTypeError("position", "an integer", offsetOrPosition);
787
+ }
788
+ return {
789
+ buffer,
790
+ offset: 0,
791
+ length: Buffer.byteLength(buffer, typeof lengthOrEncoding === "string" ? lengthOrEncoding : undefined),
792
+ position: normalizeOptionalPosition(offsetOrPosition),
793
+ encoding: typeof lengthOrEncoding === "string" ? lengthOrEncoding : undefined,
794
+ };
795
+ }
796
+ if (!isArrayBufferView(buffer)) {
797
+ throw createInvalidArgTypeError("buffer", "a string, Buffer, TypedArray, or DataView", buffer);
798
+ }
799
+ if (lengthOrEncoding === undefined &&
800
+ position === undefined &&
801
+ isReadWriteOptionsObject(offsetOrPosition)) {
802
+ const options = (offsetOrPosition ?? {});
803
+ const { offset, length } = normalizeOffsetLength(buffer.byteLength, options.offset, options.length);
804
+ return {
805
+ buffer,
806
+ offset,
807
+ length,
808
+ position: normalizeOptionalPosition(options.position),
809
+ };
810
+ }
811
+ const { offset, length } = normalizeOffsetLength(buffer.byteLength, offsetOrPosition, typeof lengthOrEncoding === "number" ? lengthOrEncoding : undefined);
812
+ return {
813
+ buffer,
814
+ offset,
815
+ length,
816
+ position: normalizeOptionalPosition(position),
817
+ };
818
+ }
819
+ function normalizeFdInteger(fd) {
820
+ return normalizeNumberArgument("fd", fd);
821
+ }
822
+ function normalizeIoVectorBuffers(buffers) {
823
+ if (!Array.isArray(buffers)) {
824
+ throw createInvalidArgTypeError("buffers", "an ArrayBufferView[]", buffers);
825
+ }
826
+ for (const buffer of buffers) {
827
+ if (!isArrayBufferView(buffer)) {
828
+ throw createInvalidArgTypeError("buffers", "an ArrayBufferView[]", buffers);
829
+ }
830
+ }
831
+ return buffers;
832
+ }
833
+ function validateStreamFsOverride(streamFs, required) {
834
+ if (streamFs === undefined) {
835
+ return undefined;
836
+ }
837
+ if (streamFs === null || typeof streamFs !== "object") {
838
+ throw createInvalidArgTypeError("options.fs", "an object", streamFs);
839
+ }
840
+ const typed = streamFs;
841
+ for (const key of required) {
842
+ if (typeof typed[key] !== "function") {
843
+ throw createInvalidPropertyTypeError(`options.fs.${String(key)}`, typed[key]);
844
+ }
845
+ }
846
+ return typed;
847
+ }
848
+ function normalizeStreamFd(fd) {
849
+ if (fd === undefined) {
850
+ return undefined;
851
+ }
852
+ if (fd instanceof FileHandle) {
853
+ return fd;
854
+ }
855
+ return normalizeNumberArgument("fd", fd);
856
+ }
857
+ function normalizeStreamPath(pathValue, fd) {
858
+ if (pathValue === null) {
859
+ if (fd === undefined) {
860
+ throw createInvalidArgTypeError("path", "of type string or an instance of Buffer or URL", pathValue);
861
+ }
862
+ return null;
863
+ }
864
+ if (typeof pathValue === "string" || Buffer.isBuffer(pathValue)) {
865
+ return pathValue;
866
+ }
867
+ if (pathValue instanceof URL) {
868
+ if (pathValue.protocol === "file:") {
869
+ return pathValue.pathname;
870
+ }
871
+ throw createInvalidArgTypeError("path", "of type string or an instance of Buffer or URL", pathValue);
872
+ }
873
+ throw createInvalidArgTypeError("path", "of type string or an instance of Buffer or URL", pathValue);
874
+ }
875
+ function normalizeStreamStartEnd(options) {
876
+ const start = options?.start;
877
+ const end = options?.end;
878
+ if (start !== undefined && typeof start !== "number") {
879
+ throw createInvalidArgTypeError("start", "of type number", start);
880
+ }
881
+ if (end !== undefined && typeof end !== "number") {
882
+ throw createInvalidArgTypeError("end", "of type number", end);
883
+ }
884
+ const normalizedStart = start;
885
+ const normalizedEnd = end;
886
+ if (normalizedStart !== undefined && (!Number.isFinite(normalizedStart) || normalizedStart < 0)) {
887
+ throw createOutOfRangeError("start", ">= 0", start);
888
+ }
889
+ if (normalizedEnd !== undefined && (!Number.isFinite(normalizedEnd) || normalizedEnd < 0)) {
890
+ throw createOutOfRangeError("end", ">= 0", end);
891
+ }
892
+ if (normalizedStart !== undefined &&
893
+ normalizedEnd !== undefined &&
894
+ normalizedStart > normalizedEnd) {
895
+ throw createOutOfRangeError("start", `<= "end" (here: ${normalizedEnd})`, normalizedStart);
896
+ }
897
+ const highWaterMarkCandidate = options?.highWaterMark ?? options?.bufferSize;
898
+ const highWaterMark = typeof highWaterMarkCandidate === "number" && Number.isFinite(highWaterMarkCandidate) && highWaterMarkCandidate > 0
899
+ ? Math.floor(highWaterMarkCandidate)
900
+ : 65536;
901
+ return {
902
+ start: normalizedStart,
903
+ end: normalizedEnd,
904
+ highWaterMark,
905
+ autoClose: options?.autoClose !== false,
906
+ };
907
+ }
908
+ class ReadStream {
909
+ _options;
910
+ bytesRead = 0;
911
+ path;
912
+ pending = true;
913
+ readable = true;
914
+ readableAborted = false;
915
+ readableDidRead = false;
916
+ readableEncoding = null;
917
+ readableEnded = false;
918
+ readableFlowing = null;
919
+ readableHighWaterMark = 65536;
920
+ readableLength = 0;
921
+ readableObjectMode = false;
922
+ destroyed = false;
923
+ closed = false;
924
+ errored = null;
925
+ fd = null;
926
+ autoClose = true;
927
+ start;
928
+ end;
929
+ _listeners = new Map();
930
+ _started = false;
931
+ _reading = false;
932
+ _readScheduled = false;
933
+ _opening = false;
934
+ _remaining = null;
935
+ _position = null;
936
+ _fileHandle = null;
937
+ _streamFs;
938
+ _signal;
939
+ _handleCloseListener;
940
+ constructor(filePath, _options) {
941
+ this._options = _options;
942
+ const fdOption = normalizeStreamFd(_options?.fd);
943
+ const optionsRecord = (_options ?? {});
944
+ const streamState = normalizeStreamStartEnd(optionsRecord);
945
+ this.path = filePath;
946
+ this.start = streamState.start;
947
+ this.end = streamState.end;
948
+ this.autoClose = streamState.autoClose;
949
+ this.readableHighWaterMark = streamState.highWaterMark;
950
+ this.readableEncoding = _options?.encoding ?? null;
951
+ this._position = this.start ?? null;
952
+ this._remaining =
953
+ this.end !== undefined ? this.end - (this.start ?? 0) + 1 : null;
954
+ this._signal = validateAbortSignal(_options?.signal);
955
+ if (fdOption instanceof FileHandle) {
956
+ if (_options?.fs !== undefined) {
957
+ const error = new Error("The FileHandle with fs method is not implemented");
958
+ error.code = "ERR_METHOD_NOT_IMPLEMENTED";
959
+ throw error;
960
+ }
961
+ this._fileHandle = fdOption;
962
+ this.fd = fdOption.fd;
963
+ this.pending = false;
964
+ this._handleCloseListener = () => {
965
+ if (!this.closed) {
966
+ this.closed = true;
967
+ this.destroyed = true;
968
+ this.readable = false;
969
+ this.emit("close");
970
+ }
971
+ };
972
+ this._fileHandle.on("close", this._handleCloseListener);
973
+ }
974
+ else {
975
+ this._streamFs = validateStreamFsOverride(_options?.fs, ["open", "read", "close"]);
976
+ if (typeof fdOption === "number") {
977
+ this.fd = fdOption;
978
+ this.pending = false;
979
+ }
980
+ }
981
+ if (this._signal) {
982
+ if (this._signal.aborted) {
983
+ queueMicrotask(() => {
984
+ void this._abort(this._signal?.reason);
985
+ });
986
+ }
987
+ else {
988
+ this._signal.addEventListener("abort", () => {
989
+ void this._abort(this._signal?.reason);
990
+ });
991
+ }
992
+ }
993
+ if (this.fd === null) {
994
+ queueMicrotask(() => {
995
+ void this._openIfNeeded();
996
+ });
997
+ }
998
+ }
999
+ _emitOpen(fd) {
1000
+ this.fd = fd;
1001
+ this.pending = false;
1002
+ this.emit("open", fd);
1003
+ if (this._started || this.readableFlowing) {
1004
+ this._scheduleRead();
1005
+ }
1006
+ }
1007
+ async _openIfNeeded() {
1008
+ if (this.fd !== null || this._opening || this.destroyed || this.closed) {
1009
+ return;
1010
+ }
1011
+ const pathStr = typeof this.path === "string"
1012
+ ? this.path
1013
+ : this.path instanceof Buffer
1014
+ ? this.path.toString()
1015
+ : null;
1016
+ if (!pathStr) {
1017
+ this._handleStreamError(createFsError("EBADF", "EBADF: bad file descriptor", "read"));
1018
+ return;
1019
+ }
1020
+ this._opening = true;
1021
+ const opener = (this._streamFs?.open ?? fs.open).bind(this._streamFs ?? fs);
1022
+ opener(pathStr, "r", 0o666, (error, fd) => {
1023
+ this._opening = false;
1024
+ if (error || typeof fd !== "number") {
1025
+ this._handleStreamError(error ?? createFsError("EBADF", "EBADF: bad file descriptor", "open"));
1026
+ return;
1027
+ }
1028
+ this._emitOpen(fd);
1029
+ });
1030
+ }
1031
+ async _closeUnderlying() {
1032
+ if (this._fileHandle) {
1033
+ if (!this._fileHandle.closed) {
1034
+ await this._fileHandle.close();
1035
+ }
1036
+ return;
1037
+ }
1038
+ if (this.fd !== null && this.fd >= 0) {
1039
+ const fd = this.fd;
1040
+ const closer = (this._streamFs?.close ?? fs.close).bind(this._streamFs ?? fs);
1041
+ await new Promise((resolve) => {
1042
+ closer(fd, () => resolve());
1043
+ });
1044
+ this.fd = -1;
1045
+ }
1046
+ }
1047
+ _scheduleRead() {
1048
+ if (this._readScheduled || this._reading || this.readableFlowing === false || this.destroyed || this.closed) {
1049
+ return;
1050
+ }
1051
+ this._readScheduled = true;
1052
+ queueMicrotask(() => {
1053
+ this._readScheduled = false;
1054
+ void this._readNextChunk();
1055
+ });
1056
+ }
1057
+ async _readNextChunk() {
1058
+ if (this._reading || this.destroyed || this.closed || this.readableFlowing === false) {
1059
+ return;
1060
+ }
1061
+ throwIfAborted(this._signal);
1062
+ if (this.fd === null) {
1063
+ await this._openIfNeeded();
1064
+ return;
1065
+ }
1066
+ if (this._remaining === 0) {
1067
+ await this._finishReadable();
1068
+ return;
1069
+ }
1070
+ const nextLength = this._remaining === null
1071
+ ? this.readableHighWaterMark
1072
+ : Math.min(this.readableHighWaterMark, this._remaining);
1073
+ const target = Buffer.alloc(nextLength);
1074
+ this._reading = true;
1075
+ const onRead = async (error, bytesRead = 0) => {
1076
+ this._reading = false;
1077
+ if (error) {
1078
+ this._handleStreamError(error);
1079
+ return;
1080
+ }
1081
+ if (bytesRead === 0) {
1082
+ await this._finishReadable();
1083
+ return;
1084
+ }
1085
+ this.bytesRead += bytesRead;
1086
+ this.readableDidRead = true;
1087
+ if (typeof this._position === "number") {
1088
+ this._position += bytesRead;
1089
+ }
1090
+ if (this._remaining !== null) {
1091
+ this._remaining -= bytesRead;
1092
+ }
1093
+ const chunk = target.subarray(0, bytesRead);
1094
+ this.emit("data", this.readableEncoding ? chunk.toString(this.readableEncoding) : Buffer.from(chunk));
1095
+ if (this._remaining === 0) {
1096
+ await this._finishReadable();
1097
+ return;
1098
+ }
1099
+ this._scheduleRead();
1100
+ };
1101
+ if (this._fileHandle) {
1102
+ try {
1103
+ const result = await this._fileHandle.read(target, 0, nextLength, this._position);
1104
+ await onRead(null, result.bytesRead);
1105
+ }
1106
+ catch (error) {
1107
+ await onRead(error);
1108
+ }
1109
+ return;
1110
+ }
1111
+ const reader = (this._streamFs?.read ?? fs.read).bind(this._streamFs ?? fs);
1112
+ reader(this.fd, target, 0, nextLength, this._position, (error, bytesRead) => {
1113
+ void onRead(error, bytesRead ?? 0);
1114
+ });
1115
+ }
1116
+ async _finishReadable() {
1117
+ if (this.readableEnded) {
1118
+ return;
1119
+ }
1120
+ this.readable = false;
1121
+ this.readableEnded = true;
1122
+ this.emit("end");
1123
+ if (this.autoClose) {
1124
+ this.destroy();
1125
+ }
1126
+ }
1127
+ _handleStreamError(error) {
1128
+ if (this.closed) {
1129
+ return;
1130
+ }
1131
+ this.errored = error;
1132
+ this.emit("error", error);
1133
+ if (this.autoClose) {
1134
+ this.destroy();
1135
+ }
1136
+ else {
1137
+ this.readable = false;
1138
+ }
1139
+ }
1140
+ async _abort(reason) {
1141
+ if (this.closed || this.destroyed) {
1142
+ return;
1143
+ }
1144
+ this.readableAborted = true;
1145
+ this.errored = createAbortError(reason);
1146
+ this.emit("error", this.errored);
1147
+ if (this._fileHandle) {
1148
+ this.destroyed = true;
1149
+ this.readable = false;
1150
+ this.closed = true;
1151
+ this.emit("close");
1152
+ return;
1153
+ }
1154
+ if (this.autoClose) {
1155
+ this.destroy();
1156
+ return;
1157
+ }
1158
+ this.closed = true;
1159
+ this.emit("close");
1160
+ }
1161
+ async _readAllContent() {
1162
+ const chunks = [];
1163
+ let totalLength = 0;
1164
+ const savedFlowing = this.readableFlowing;
1165
+ this.readableFlowing = false;
1166
+ while (this._remaining !== 0) {
1167
+ if (this.fd === null) {
1168
+ await this._openIfNeeded();
1169
+ }
1170
+ if (this.fd === null) {
1171
+ break;
1172
+ }
1173
+ const nextLength = this._remaining === null
1174
+ ? FILE_HANDLE_READ_CHUNK_BYTES
1175
+ : Math.min(FILE_HANDLE_READ_CHUNK_BYTES, this._remaining);
1176
+ const target = Buffer.alloc(nextLength);
1177
+ let bytesRead = 0;
1178
+ if (this._fileHandle) {
1179
+ bytesRead = (await this._fileHandle.read(target, 0, nextLength, this._position)).bytesRead;
1180
+ }
1181
+ else {
1182
+ bytesRead = fs.readSync(this.fd, target, 0, nextLength, this._position);
1183
+ }
1184
+ if (bytesRead === 0) {
1185
+ break;
1186
+ }
1187
+ const chunk = target.subarray(0, bytesRead);
1188
+ chunks.push(chunk);
1189
+ totalLength += bytesRead;
1190
+ if (typeof this._position === "number") {
1191
+ this._position += bytesRead;
1192
+ }
1193
+ if (this._remaining !== null) {
1194
+ this._remaining -= bytesRead;
1195
+ }
1196
+ }
1197
+ this.readableFlowing = savedFlowing;
1198
+ return Buffer.concat(chunks, totalLength);
1199
+ }
1200
+ on(event, listener) {
1201
+ const listeners = this._listeners.get(event) ?? [];
1202
+ listeners.push(listener);
1203
+ this._listeners.set(event, listeners);
1204
+ if (event === "data") {
1205
+ this._started = true;
1206
+ this.readableFlowing = true;
1207
+ this._scheduleRead();
1208
+ }
1209
+ return this;
1210
+ }
1211
+ once(event, listener) {
1212
+ const wrapper = (...args) => {
1213
+ this.off(event, wrapper);
1214
+ listener(...args);
1215
+ };
1216
+ wrapper._originalListener = listener;
1217
+ return this.on(event, wrapper);
1218
+ }
1219
+ off(event, listener) {
1220
+ const listeners = this._listeners.get(event);
1221
+ if (!listeners) {
1222
+ return this;
1223
+ }
1224
+ const index = listeners.findIndex((fn) => fn === listener || fn._originalListener === listener);
1225
+ if (index >= 0) {
1226
+ listeners.splice(index, 1);
1227
+ }
1228
+ return this;
1229
+ }
1230
+ removeListener(event, listener) {
1231
+ return this.off(event, listener);
1232
+ }
1233
+ removeAllListeners(event) {
1234
+ if (event === undefined) {
1235
+ this._listeners.clear();
1236
+ }
1237
+ else {
1238
+ this._listeners.delete(event);
1239
+ }
1240
+ return this;
1241
+ }
1242
+ emit(event, ...args) {
1243
+ const listeners = this._listeners.get(event);
1244
+ if (!listeners?.length) {
1245
+ return false;
1246
+ }
1247
+ listeners.slice().forEach((listener) => listener(...args));
1248
+ return true;
1249
+ }
1250
+ read() {
1251
+ return null;
1252
+ }
1253
+ pipe(destination, _options) {
1254
+ this.on("data", (chunk) => {
1255
+ destination.write(chunk);
1256
+ });
1257
+ this.on("end", () => {
1258
+ destination.end?.();
1259
+ });
1260
+ this.resume();
1261
+ return destination;
1262
+ }
1263
+ unpipe(_destination) {
1264
+ return this;
1265
+ }
1266
+ pause() {
1267
+ this.readableFlowing = false;
1268
+ return this;
1269
+ }
1270
+ resume() {
1271
+ this._started = true;
1272
+ this.readableFlowing = true;
1273
+ this._scheduleRead();
1274
+ return this;
1275
+ }
1276
+ setEncoding(encoding) {
1277
+ this.readableEncoding = encoding;
1278
+ return this;
1279
+ }
1280
+ destroy(error) {
1281
+ if (this.destroyed) {
1282
+ return this;
1283
+ }
1284
+ this.destroyed = true;
1285
+ this.readable = false;
1286
+ if (error) {
1287
+ this.errored = error;
1288
+ this.emit("error", error);
1289
+ }
1290
+ queueMicrotask(() => {
1291
+ void this._closeUnderlying().then(() => {
1292
+ if (!this.closed) {
1293
+ this.closed = true;
1294
+ this.emit("close");
1295
+ }
1296
+ });
1297
+ });
1298
+ return this;
1299
+ }
1300
+ close(callback) {
1301
+ this.destroy();
1302
+ if (callback) {
1303
+ queueMicrotask(() => callback(null));
1304
+ }
1305
+ }
1306
+ async *[Symbol.asyncIterator]() {
1307
+ const content = await this._readAllContent();
1308
+ yield this.readableEncoding ? content.toString(this.readableEncoding) : content;
1309
+ }
1310
+ }
1311
+ const MAX_WRITE_STREAM_BYTES = 16 * 1024 * 1024;
1312
+ class WriteStream {
1313
+ _options;
1314
+ bytesWritten = 0;
1315
+ path;
1316
+ pending = false;
1317
+ writable = true;
1318
+ writableAborted = false;
1319
+ writableEnded = false;
1320
+ writableFinished = false;
1321
+ writableHighWaterMark = 16384;
1322
+ writableLength = 0;
1323
+ writableObjectMode = false;
1324
+ writableCorked = 0;
1325
+ destroyed = false;
1326
+ closed = false;
1327
+ errored = null;
1328
+ writableNeedDrain = false;
1329
+ fd = null;
1330
+ autoClose = true;
1331
+ _chunks = [];
1332
+ _listeners = new Map();
1333
+ _fileHandle = null;
1334
+ _streamFs;
1335
+ constructor(filePath, _options) {
1336
+ this._options = _options;
1337
+ const fdOption = normalizeStreamFd(_options?.fd);
1338
+ this.path = filePath;
1339
+ this.autoClose = _options?.autoClose !== false;
1340
+ this._streamFs = validateStreamFsOverride(_options?.fs, ["open", "close", "write"]);
1341
+ if (_options?.fs !== undefined) {
1342
+ validateStreamFsOverride(_options?.fs, ["writev"]);
1343
+ }
1344
+ if (fdOption instanceof FileHandle) {
1345
+ this._fileHandle = fdOption;
1346
+ this.fd = fdOption.fd;
1347
+ return;
1348
+ }
1349
+ if (typeof fdOption === "number") {
1350
+ this.fd = fdOption;
1351
+ return;
1352
+ }
1353
+ const pathStr = typeof this.path === "string"
1354
+ ? this.path
1355
+ : this.path instanceof Buffer
1356
+ ? this.path.toString()
1357
+ : null;
1358
+ if (!pathStr) {
1359
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "write");
1360
+ }
1361
+ this.fd = fs.openSync(pathStr, _options?.flags ?? "w", _options?.mode);
1362
+ queueMicrotask(() => {
1363
+ if (this.fd !== null && this.fd >= 0) {
1364
+ this.emit("open", this.fd);
1365
+ }
1366
+ });
1367
+ }
1368
+ async _closeUnderlying() {
1369
+ if (this._fileHandle) {
1370
+ if (!this._fileHandle.closed) {
1371
+ await this._fileHandle.close();
1372
+ }
1373
+ return;
1374
+ }
1375
+ if (this.fd !== null && this.fd >= 0) {
1376
+ const fd = this.fd;
1377
+ const closer = (this._streamFs?.close ?? fs.close).bind(this._streamFs ?? fs);
1378
+ await new Promise((resolve) => {
1379
+ closer(fd, () => resolve());
1380
+ });
1381
+ this.fd = -1;
1382
+ }
1383
+ }
1384
+ close(callback) {
1385
+ queueMicrotask(() => {
1386
+ void this._closeUnderlying().then(() => {
1387
+ if (!this.closed) {
1388
+ this.closed = true;
1389
+ this.writable = false;
1390
+ this.emit("close");
1391
+ }
1392
+ callback?.(null);
1393
+ });
1394
+ });
1395
+ }
1396
+ write(chunk, encodingOrCallback, callback) {
1397
+ if (this.writableEnded || this.destroyed) {
1398
+ const error = new Error("write after end");
1399
+ const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
1400
+ queueMicrotask(() => cb?.(error));
1401
+ return false;
1402
+ }
1403
+ let data;
1404
+ if (typeof chunk === "string") {
1405
+ data = Buffer.from(chunk, typeof encodingOrCallback === "string" ? encodingOrCallback : "utf8");
1406
+ }
1407
+ else if (isArrayBufferView(chunk)) {
1408
+ data = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
1409
+ }
1410
+ else {
1411
+ throw createInvalidArgTypeError("chunk", "a string, Buffer, TypedArray, or DataView", chunk);
1412
+ }
1413
+ if (this.writableLength + data.length > MAX_WRITE_STREAM_BYTES) {
1414
+ const error = new Error(`WriteStream buffer exceeded ${MAX_WRITE_STREAM_BYTES} bytes`);
1415
+ this.errored = error;
1416
+ this.destroyed = true;
1417
+ this.writable = false;
1418
+ const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
1419
+ queueMicrotask(() => {
1420
+ cb?.(error);
1421
+ this.emit("error", error);
1422
+ });
1423
+ return false;
1424
+ }
1425
+ this._chunks.push(data);
1426
+ this.bytesWritten += data.length;
1427
+ this.writableLength += data.length;
1428
+ const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
1429
+ queueMicrotask(() => cb?.(null));
1430
+ return true;
1431
+ }
1432
+ end(chunkOrCb, encodingOrCallback, callback) {
1433
+ if (this.writableEnded) {
1434
+ return this;
1435
+ }
1436
+ let cb;
1437
+ if (typeof chunkOrCb === "function") {
1438
+ cb = chunkOrCb;
1439
+ }
1440
+ else if (typeof encodingOrCallback === "function") {
1441
+ cb = encodingOrCallback;
1442
+ if (chunkOrCb !== undefined && chunkOrCb !== null) {
1443
+ this.write(chunkOrCb);
1444
+ }
1445
+ }
1446
+ else {
1447
+ cb = callback;
1448
+ if (chunkOrCb !== undefined && chunkOrCb !== null) {
1449
+ this.write(chunkOrCb, encodingOrCallback);
1450
+ }
1451
+ }
1452
+ this.writableEnded = true;
1453
+ this.writable = false;
1454
+ this.writableFinished = true;
1455
+ this.writableLength = 0;
1456
+ queueMicrotask(() => {
1457
+ void (async () => {
1458
+ try {
1459
+ if (this._fileHandle) {
1460
+ for (const chunk of this._chunks) {
1461
+ await this._fileHandle.write(chunk, 0, chunk.byteLength, undefined);
1462
+ }
1463
+ if (this.autoClose && !this._fileHandle.closed) {
1464
+ await this._fileHandle.close();
1465
+ }
1466
+ }
1467
+ else if (this.fd !== null && this.fd >= 0) {
1468
+ for (const chunk of this._chunks) {
1469
+ fs.writeSync(this.fd, chunk, 0, chunk.byteLength, null);
1470
+ }
1471
+ if (this.autoClose) {
1472
+ await this._closeUnderlying();
1473
+ }
1474
+ }
1475
+ else {
1476
+ const pathStr = typeof this.path === "string"
1477
+ ? this.path
1478
+ : this.path instanceof Buffer
1479
+ ? this.path.toString()
1480
+ : null;
1481
+ if (!pathStr) {
1482
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "write");
1483
+ }
1484
+ fs.writeFileSync(pathStr, Buffer.concat(this._chunks.map((chunk) => Buffer.from(chunk))));
1485
+ }
1486
+ this.emit("finish");
1487
+ if (this.autoClose && !this.closed) {
1488
+ this.closed = true;
1489
+ this.emit("close");
1490
+ }
1491
+ cb?.();
1492
+ }
1493
+ catch (error) {
1494
+ this.errored = error;
1495
+ this.emit("error", error);
1496
+ }
1497
+ })();
1498
+ });
1499
+ return this;
1500
+ }
1501
+ setDefaultEncoding(_encoding) {
1502
+ return this;
1503
+ }
1504
+ cork() {
1505
+ this.writableCorked++;
1506
+ }
1507
+ uncork() {
1508
+ if (this.writableCorked > 0) {
1509
+ this.writableCorked--;
1510
+ }
1511
+ }
1512
+ destroy(error) {
1513
+ if (this.destroyed) {
1514
+ return this;
1515
+ }
1516
+ this.destroyed = true;
1517
+ this.writable = false;
1518
+ if (error) {
1519
+ this.errored = error;
1520
+ this.emit("error", error);
1521
+ }
1522
+ queueMicrotask(() => {
1523
+ void this._closeUnderlying().then(() => {
1524
+ if (!this.closed) {
1525
+ this.closed = true;
1526
+ this.emit("close");
1527
+ }
1528
+ });
1529
+ });
1530
+ return this;
1531
+ }
1532
+ addListener(event, listener) {
1533
+ return this.on(event, listener);
1534
+ }
1535
+ on(event, listener) {
1536
+ const listeners = this._listeners.get(event) ?? [];
1537
+ listeners.push(listener);
1538
+ this._listeners.set(event, listeners);
1539
+ return this;
1540
+ }
1541
+ once(event, listener) {
1542
+ const wrapper = (...args) => {
1543
+ this.removeListener(event, wrapper);
1544
+ listener(...args);
1545
+ };
1546
+ return this.on(event, wrapper);
1547
+ }
1548
+ removeListener(event, listener) {
1549
+ const listeners = this._listeners.get(event);
1550
+ if (!listeners) {
1551
+ return this;
1552
+ }
1553
+ const index = listeners.indexOf(listener);
1554
+ if (index >= 0) {
1555
+ listeners.splice(index, 1);
1556
+ }
1557
+ return this;
1558
+ }
1559
+ off(event, listener) {
1560
+ return this.removeListener(event, listener);
1561
+ }
1562
+ removeAllListeners(event) {
1563
+ if (event === undefined) {
1564
+ this._listeners.clear();
1565
+ }
1566
+ else {
1567
+ this._listeners.delete(event);
1568
+ }
1569
+ return this;
1570
+ }
1571
+ emit(event, ...args) {
1572
+ const listeners = this._listeners.get(event);
1573
+ if (!listeners?.length) {
1574
+ return false;
1575
+ }
1576
+ listeners.slice().forEach((listener) => listener(...args));
1577
+ return true;
1578
+ }
1579
+ pipe(destination, _options) {
1580
+ return destination;
1581
+ }
1582
+ unpipe(_destination) {
1583
+ return this;
1584
+ }
1585
+ [Symbol.asyncDispose]() {
1586
+ return Promise.resolve();
1587
+ }
1588
+ }
1589
+ const ReadStreamClass = ReadStream;
1590
+ const WriteStreamClass = WriteStream;
1591
+ const ReadStreamFactory = function ReadStream(path, options) {
1592
+ validateEncodingOption(options);
1593
+ return new ReadStreamClass(path, options);
1594
+ };
1595
+ ReadStreamFactory.prototype = ReadStream.prototype;
1596
+ const WriteStreamFactory = function WriteStream(path, options) {
1597
+ validateEncodingOption(options);
1598
+ validateWriteStreamStartOption((options ?? {}));
1599
+ return new WriteStreamClass(path, options);
1600
+ };
1601
+ WriteStreamFactory.prototype = WriteStream.prototype;
1602
+ // Parse flags string to number
1603
+ function parseFlags(flags) {
1604
+ if (typeof flags === "number")
1605
+ return flags;
1606
+ const flagMap = {
1607
+ r: O_RDONLY,
1608
+ "r+": O_RDWR,
1609
+ rs: O_RDONLY,
1610
+ "rs+": O_RDWR,
1611
+ w: O_WRONLY | O_CREAT | O_TRUNC,
1612
+ "w+": O_RDWR | O_CREAT | O_TRUNC,
1613
+ a: O_WRONLY | O_APPEND | O_CREAT,
1614
+ "a+": O_RDWR | O_APPEND | O_CREAT,
1615
+ wx: O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
1616
+ xw: O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
1617
+ "wx+": O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
1618
+ "xw+": O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
1619
+ ax: O_WRONLY | O_APPEND | O_CREAT | O_EXCL,
1620
+ xa: O_WRONLY | O_APPEND | O_CREAT | O_EXCL,
1621
+ "ax+": O_RDWR | O_APPEND | O_CREAT | O_EXCL,
1622
+ "xa+": O_RDWR | O_APPEND | O_CREAT | O_EXCL,
1623
+ };
1624
+ if (flags in flagMap)
1625
+ return flagMap[flags];
1626
+ throw new Error("Unknown file flag: " + flags);
1627
+ }
1628
+ // Helper to create fs errors
1629
+ function createFsError(code, message, syscall, path) {
1630
+ const err = new Error(message);
1631
+ err.code = code;
1632
+ err.errno = code === "ENOENT" ? -2 : code === "EACCES" ? -13 : code === "EBADF" ? -9 : code === "EMFILE" ? -24 : -1;
1633
+ err.syscall = syscall;
1634
+ if (path)
1635
+ err.path = path;
1636
+ return err;
1637
+ }
1638
+ /** Wrap a bridge call with ENOENT/EACCES error re-creation. */
1639
+ function bridgeCall(fn, syscall, path) {
1640
+ try {
1641
+ return fn();
1642
+ }
1643
+ catch (err) {
1644
+ const msg = err.message || String(err);
1645
+ if (msg.includes("ENOENT") || msg.includes("no such file or directory") || msg.includes("not found")) {
1646
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, ${syscall} '${path}'`, syscall, path);
1647
+ }
1648
+ if (msg.includes("EACCES") || msg.includes("permission denied")) {
1649
+ throw createFsError("EACCES", `EACCES: permission denied, ${syscall} '${path}'`, syscall, path);
1650
+ }
1651
+ if (msg.includes("EEXIST") || msg.includes("file already exists")) {
1652
+ throw createFsError("EEXIST", `EEXIST: file already exists, ${syscall} '${path}'`, syscall, path);
1653
+ }
1654
+ if (msg.includes("EINVAL") || msg.includes("invalid argument")) {
1655
+ throw createFsError("EINVAL", `EINVAL: invalid argument, ${syscall} '${path}'`, syscall, path);
1656
+ }
1657
+ throw err;
1658
+ }
1659
+ }
1660
+ // Glob pattern matching helper — converts glob to regex and walks VFS recursively
1661
+ function _globToRegex(pattern) {
1662
+ // Determine base directory vs glob portion
1663
+ let regexStr = "";
1664
+ let i = 0;
1665
+ while (i < pattern.length) {
1666
+ const ch = pattern[i];
1667
+ if (ch === "*" && pattern[i + 1] === "*") {
1668
+ // ** matches any depth of directories
1669
+ if (pattern[i + 2] === "/") {
1670
+ regexStr += "(?:.+/)?";
1671
+ i += 3;
1672
+ }
1673
+ else {
1674
+ regexStr += ".*";
1675
+ i += 2;
1676
+ }
1677
+ }
1678
+ else if (ch === "*") {
1679
+ regexStr += "[^/]*";
1680
+ i++;
1681
+ }
1682
+ else if (ch === "?") {
1683
+ regexStr += "[^/]";
1684
+ i++;
1685
+ }
1686
+ else if (ch === "{") {
1687
+ const close = pattern.indexOf("}", i);
1688
+ if (close !== -1) {
1689
+ const alternatives = pattern.slice(i + 1, close).split(",");
1690
+ regexStr += "(?:" + alternatives.map(a => a.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, "[^/]*")).join("|") + ")";
1691
+ i = close + 1;
1692
+ }
1693
+ else {
1694
+ regexStr += "\\{";
1695
+ i++;
1696
+ }
1697
+ }
1698
+ else if (ch === "[") {
1699
+ const close = pattern.indexOf("]", i);
1700
+ if (close !== -1) {
1701
+ regexStr += pattern.slice(i, close + 1);
1702
+ i = close + 1;
1703
+ }
1704
+ else {
1705
+ regexStr += "\\[";
1706
+ i++;
1707
+ }
1708
+ }
1709
+ else if (".+^${}()|[]\\".includes(ch)) {
1710
+ regexStr += "\\" + ch;
1711
+ i++;
1712
+ }
1713
+ else {
1714
+ regexStr += ch;
1715
+ i++;
1716
+ }
1717
+ }
1718
+ return new RegExp("^" + regexStr + "$");
1719
+ }
1720
+ function _globGetBase(pattern) {
1721
+ // Find the longest directory prefix that has no glob characters
1722
+ const parts = pattern.split("/");
1723
+ const baseParts = [];
1724
+ for (const part of parts) {
1725
+ if (/[*?{}\[\]]/.test(part))
1726
+ break;
1727
+ baseParts.push(part);
1728
+ }
1729
+ return baseParts.join("/") || "/";
1730
+ }
1731
+ // Recursively walk VFS directory and collect matching paths
1732
+ // We use a reference to `fs` via late-binding in the fs object method
1733
+ const MAX_GLOB_DEPTH = 100; // Prevent stack overflow on deeply nested trees
1734
+ function _globCollect(pattern, results) {
1735
+ const regex = _globToRegex(pattern);
1736
+ const base = _globGetBase(pattern);
1737
+ const walk = (dir, depth) => {
1738
+ if (depth > MAX_GLOB_DEPTH)
1739
+ return;
1740
+ let entries;
1741
+ try {
1742
+ entries = _globReadDir(dir);
1743
+ }
1744
+ catch {
1745
+ return; // Directory doesn't exist or not readable
1746
+ }
1747
+ for (const entry of entries) {
1748
+ const fullPath = dir === "/" ? "/" + entry : dir + "/" + entry;
1749
+ // Check if this path matches the pattern
1750
+ if (regex.test(fullPath)) {
1751
+ results.push(fullPath);
1752
+ }
1753
+ // Recurse into directories if pattern has ** or more segments
1754
+ try {
1755
+ const stat = _globStat(fullPath);
1756
+ if (stat.isDirectory()) {
1757
+ walk(fullPath, depth + 1);
1758
+ }
1759
+ }
1760
+ catch {
1761
+ // Not a directory or stat failed — skip
1762
+ }
1763
+ }
1764
+ };
1765
+ // Start walking from the base directory
1766
+ try {
1767
+ // Check if base itself matches (edge case)
1768
+ if (regex.test(base)) {
1769
+ const stat = _globStat(base);
1770
+ if (!stat.isDirectory()) {
1771
+ results.push(base);
1772
+ return;
1773
+ }
1774
+ }
1775
+ walk(base, 0);
1776
+ }
1777
+ catch {
1778
+ // Base doesn't exist — no matches
1779
+ }
1780
+ }
1781
+ // Late-bound references — these get assigned after fs is defined
1782
+ let _globReadDir;
1783
+ let _globStat;
1784
+ // Helper to convert PathLike to string
1785
+ function toPathString(path) {
1786
+ return normalizePathLike(path);
1787
+ }
1788
+ // Note: Path normalization is handled by VirtualFileSystem, not here.
1789
+ // The VFS expects /data/* paths for Directory access, so we pass paths through unchanged.
1790
+ // The fs module implementation
1791
+ const fs = {
1792
+ // Constants
1793
+ constants: {
1794
+ // File Access Constants
1795
+ F_OK: 0,
1796
+ R_OK: 4,
1797
+ W_OK: 2,
1798
+ X_OK: 1,
1799
+ // File Copy Constants
1800
+ COPYFILE_EXCL: 1,
1801
+ COPYFILE_FICLONE: 2,
1802
+ COPYFILE_FICLONE_FORCE: 4,
1803
+ // File Open Constants
1804
+ O_RDONLY,
1805
+ O_WRONLY,
1806
+ O_RDWR,
1807
+ O_CREAT,
1808
+ O_EXCL,
1809
+ O_NOCTTY: 256,
1810
+ O_TRUNC,
1811
+ O_APPEND,
1812
+ O_DIRECTORY: 65536,
1813
+ O_NOATIME: 262144,
1814
+ O_NOFOLLOW: 131072,
1815
+ O_SYNC: 1052672,
1816
+ O_DSYNC: 4096,
1817
+ O_SYMLINK: 2097152,
1818
+ O_DIRECT: 16384,
1819
+ O_NONBLOCK: 2048,
1820
+ // File Type Constants
1821
+ S_IFMT: 61440,
1822
+ S_IFREG: 32768,
1823
+ S_IFDIR: 16384,
1824
+ S_IFCHR: 8192,
1825
+ S_IFBLK: 24576,
1826
+ S_IFIFO: 4096,
1827
+ S_IFLNK: 40960,
1828
+ S_IFSOCK: 49152,
1829
+ // File Mode Constants
1830
+ S_IRWXU: 448,
1831
+ S_IRUSR: 256,
1832
+ S_IWUSR: 128,
1833
+ S_IXUSR: 64,
1834
+ S_IRWXG: 56,
1835
+ S_IRGRP: 32,
1836
+ S_IWGRP: 16,
1837
+ S_IXGRP: 8,
1838
+ S_IRWXO: 7,
1839
+ S_IROTH: 4,
1840
+ S_IWOTH: 2,
1841
+ S_IXOTH: 1,
1842
+ UV_FS_O_FILEMAP: 536870912,
1843
+ },
1844
+ Stats,
1845
+ Dirent,
1846
+ Dir,
1847
+ // Sync methods
1848
+ readFileSync(path, options) {
1849
+ validateEncodingOption(options);
1850
+ const rawPath = typeof path === "number"
1851
+ ? _fdGetPath.applySync(undefined, [normalizeFdInteger(path)])
1852
+ : normalizePathLike(path);
1853
+ if (!rawPath)
1854
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "read");
1855
+ const pathStr = rawPath;
1856
+ const encoding = typeof options === "string" ? options : options?.encoding;
1857
+ try {
1858
+ if (encoding) {
1859
+ // Text mode - use text read
1860
+ const content = _fs.readFile.applySyncPromise(undefined, [pathStr]);
1861
+ return content;
1862
+ }
1863
+ else {
1864
+ // Binary mode - use binary read with base64 encoding
1865
+ const base64Content = _fs.readFileBinary.applySyncPromise(undefined, [pathStr]);
1866
+ return Buffer.from(base64Content, "base64");
1867
+ }
1868
+ }
1869
+ catch (err) {
1870
+ const errMsg = err.message || String(err);
1871
+ // Convert various "not found" errors to proper ENOENT
1872
+ if (errMsg.includes("entry not found") ||
1873
+ errMsg.includes("not found") ||
1874
+ errMsg.includes("ENOENT") ||
1875
+ errMsg.includes("no such file or directory")) {
1876
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, open '${rawPath}'`, "open", rawPath);
1877
+ }
1878
+ // Convert permission errors to proper EACCES
1879
+ if (errMsg.includes("EACCES") || errMsg.includes("permission denied")) {
1880
+ throw createFsError("EACCES", `EACCES: permission denied, open '${rawPath}'`, "open", rawPath);
1881
+ }
1882
+ throw err;
1883
+ }
1884
+ },
1885
+ writeFileSync(file, data, _options) {
1886
+ validateEncodingOption(_options);
1887
+ const rawPath = typeof file === "number"
1888
+ ? _fdGetPath.applySync(undefined, [normalizeFdInteger(file)])
1889
+ : normalizePathLike(file);
1890
+ if (!rawPath)
1891
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "write");
1892
+ const pathStr = rawPath;
1893
+ if (typeof data === "string") {
1894
+ // Text mode - use text write
1895
+ // Return the result so async callers (fs.promises) can await it.
1896
+ return _fs.writeFile.applySyncPromise(undefined, [pathStr, data]);
1897
+ }
1898
+ else if (ArrayBuffer.isView(data)) {
1899
+ // Binary mode - convert to base64 and use binary write
1900
+ const uint8 = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
1901
+ const base64 = Buffer.from(uint8).toString("base64");
1902
+ return _fs.writeFileBinary.applySyncPromise(undefined, [pathStr, base64]);
1903
+ }
1904
+ else {
1905
+ // Fallback to text mode
1906
+ return _fs.writeFile.applySyncPromise(undefined, [pathStr, String(data)]);
1907
+ }
1908
+ },
1909
+ appendFileSync(path, data, options) {
1910
+ validateEncodingOption(options);
1911
+ const existing = fs.existsSync(path)
1912
+ ? fs.readFileSync(path, "utf8")
1913
+ : "";
1914
+ const content = typeof data === "string" ? data : String(data);
1915
+ fs.writeFileSync(path, existing + content, options);
1916
+ },
1917
+ readdirSync(path, options) {
1918
+ validateEncodingOption(options);
1919
+ const rawPath = normalizePathLike(path);
1920
+ const pathStr = rawPath;
1921
+ let entriesJson;
1922
+ try {
1923
+ entriesJson = _fs.readDir.applySyncPromise(undefined, [pathStr]);
1924
+ }
1925
+ catch (err) {
1926
+ // Convert "entry not found" and similar errors to proper ENOENT
1927
+ const errMsg = err.message || String(err);
1928
+ if (errMsg.includes("entry not found") || errMsg.includes("not found")) {
1929
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, scandir '${rawPath}'`, "scandir", rawPath);
1930
+ }
1931
+ throw err;
1932
+ }
1933
+ const entries = JSON.parse(entriesJson);
1934
+ if (options?.withFileTypes) {
1935
+ return entries.map((e) => new Dirent(e.name, e.isDirectory, rawPath));
1936
+ }
1937
+ return entries.map((e) => e.name);
1938
+ },
1939
+ mkdirSync(path, options) {
1940
+ const rawPath = normalizePathLike(path);
1941
+ const pathStr = rawPath;
1942
+ const recursive = typeof options === "object" ? options?.recursive ?? false : false;
1943
+ _fs.mkdir.applySyncPromise(undefined, [pathStr, recursive]);
1944
+ return recursive ? rawPath : undefined;
1945
+ },
1946
+ rmdirSync(path, _options) {
1947
+ const pathStr = normalizePathLike(path);
1948
+ _fs.rmdir.applySyncPromise(undefined, [pathStr]);
1949
+ },
1950
+ rmSync(path, options) {
1951
+ const pathStr = toPathString(path);
1952
+ const opts = options || {};
1953
+ try {
1954
+ const stats = fs.statSync(pathStr);
1955
+ if (stats.isDirectory()) {
1956
+ if (opts.recursive) {
1957
+ // Recursively remove directory contents
1958
+ const entries = fs.readdirSync(pathStr);
1959
+ for (const entry of entries) {
1960
+ const entryPath = pathStr.endsWith("/") ? pathStr + entry : pathStr + "/" + entry;
1961
+ const entryStats = fs.statSync(entryPath);
1962
+ if (entryStats.isDirectory()) {
1963
+ fs.rmSync(entryPath, { recursive: true });
1964
+ }
1965
+ else {
1966
+ fs.unlinkSync(entryPath);
1967
+ }
1968
+ }
1969
+ fs.rmdirSync(pathStr);
1970
+ }
1971
+ else {
1972
+ fs.rmdirSync(pathStr);
1973
+ }
1974
+ }
1975
+ else {
1976
+ fs.unlinkSync(pathStr);
1977
+ }
1978
+ }
1979
+ catch (e) {
1980
+ if (opts.force && e.code === "ENOENT") {
1981
+ return; // Ignore ENOENT when force is true
1982
+ }
1983
+ throw e;
1984
+ }
1985
+ },
1986
+ existsSync(path) {
1987
+ const pathStr = tryNormalizeExistsPath(path);
1988
+ if (!pathStr) {
1989
+ return false;
1990
+ }
1991
+ return _fs.exists.applySyncPromise(undefined, [pathStr]);
1992
+ },
1993
+ statSync(path, _options) {
1994
+ const rawPath = normalizePathLike(path);
1995
+ const pathStr = rawPath;
1996
+ let statJson;
1997
+ try {
1998
+ statJson = _fs.stat.applySyncPromise(undefined, [pathStr]);
1999
+ }
2000
+ catch (err) {
2001
+ // Convert various "not found" errors to proper ENOENT
2002
+ const errMsg = err.message || String(err);
2003
+ if (errMsg.includes("entry not found") ||
2004
+ errMsg.includes("not found") ||
2005
+ errMsg.includes("ENOENT") ||
2006
+ errMsg.includes("no such file or directory")) {
2007
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, stat '${rawPath}'`, "stat", rawPath);
2008
+ }
2009
+ throw err;
2010
+ }
2011
+ const stat = JSON.parse(statJson);
2012
+ return new Stats(stat);
2013
+ },
2014
+ lstatSync(path, _options) {
2015
+ const pathStr = normalizePathLike(path);
2016
+ const statJson = bridgeCall(() => _fs.lstat.applySyncPromise(undefined, [pathStr]), "lstat", pathStr);
2017
+ const stat = JSON.parse(statJson);
2018
+ return new Stats(stat);
2019
+ },
2020
+ unlinkSync(path) {
2021
+ const pathStr = normalizePathLike(path);
2022
+ _fs.unlink.applySyncPromise(undefined, [pathStr]);
2023
+ },
2024
+ renameSync(oldPath, newPath) {
2025
+ const oldPathStr = normalizePathLike(oldPath, "oldPath");
2026
+ const newPathStr = normalizePathLike(newPath, "newPath");
2027
+ _fs.rename.applySyncPromise(undefined, [oldPathStr, newPathStr]);
2028
+ },
2029
+ copyFileSync(src, dest, _mode) {
2030
+ // readFileSync and writeFileSync already normalize paths
2031
+ const content = fs.readFileSync(src);
2032
+ fs.writeFileSync(dest, content);
2033
+ },
2034
+ // Recursive copy
2035
+ cpSync(src, dest, options) {
2036
+ const srcPath = toPathString(src);
2037
+ const destPath = toPathString(dest);
2038
+ const opts = options || {};
2039
+ const srcStat = fs.statSync(srcPath);
2040
+ if (srcStat.isDirectory()) {
2041
+ if (!opts.recursive) {
2042
+ throw createFsError("ERR_FS_EISDIR", `Path is a directory: cp '${srcPath}'`, "cp", srcPath);
2043
+ }
2044
+ // Create destination directory
2045
+ try {
2046
+ fs.mkdirSync(destPath, { recursive: true });
2047
+ }
2048
+ catch {
2049
+ // May already exist
2050
+ }
2051
+ // Copy contents recursively
2052
+ const entries = fs.readdirSync(srcPath);
2053
+ for (const entry of entries) {
2054
+ const srcEntry = srcPath.endsWith("/") ? srcPath + entry : srcPath + "/" + entry;
2055
+ const destEntry = destPath.endsWith("/") ? destPath + entry : destPath + "/" + entry;
2056
+ fs.cpSync(srcEntry, destEntry, opts);
2057
+ }
2058
+ }
2059
+ else {
2060
+ // File copy
2061
+ if (opts.errorOnExist && fs.existsSync(destPath)) {
2062
+ throw createFsError("EEXIST", `EEXIST: file already exists, cp '${srcPath}' -> '${destPath}'`, "cp", destPath);
2063
+ }
2064
+ if (!opts.force && opts.force !== undefined && fs.existsSync(destPath)) {
2065
+ return; // Skip without error when force is false
2066
+ }
2067
+ fs.copyFileSync(srcPath, destPath);
2068
+ }
2069
+ },
2070
+ // Temp directory creation
2071
+ mkdtempSync(prefix, _options) {
2072
+ validateEncodingOption(_options);
2073
+ const suffix = Math.random().toString(36).slice(2, 8);
2074
+ const dirPath = prefix + suffix;
2075
+ fs.mkdirSync(dirPath, { recursive: true });
2076
+ return dirPath;
2077
+ },
2078
+ // Directory handle (sync)
2079
+ opendirSync(path, _options) {
2080
+ const pathStr = normalizePathLike(path);
2081
+ // Verify directory exists
2082
+ const stat = fs.statSync(pathStr);
2083
+ if (!stat.isDirectory()) {
2084
+ throw createFsError("ENOTDIR", `ENOTDIR: not a directory, opendir '${pathStr}'`, "opendir", pathStr);
2085
+ }
2086
+ return new Dir(pathStr);
2087
+ },
2088
+ // File descriptor methods
2089
+ openSync(path, flags, _mode) {
2090
+ const pathStr = normalizePathLike(path);
2091
+ const numFlags = parseFlags(flags ?? "r");
2092
+ const modeNum = normalizeOpenModeArgument(_mode);
2093
+ try {
2094
+ return _fdOpen.applySyncPromise(undefined, [pathStr, numFlags, modeNum]);
2095
+ }
2096
+ catch (e) {
2097
+ const msg = e?.message ?? String(e);
2098
+ if (msg.includes("ENOENT"))
2099
+ throw createFsError("ENOENT", msg, "open", pathStr);
2100
+ if (msg.includes("EMFILE"))
2101
+ throw createFsError("EMFILE", msg, "open", pathStr);
2102
+ throw e;
2103
+ }
2104
+ },
2105
+ closeSync(fd) {
2106
+ normalizeFdInteger(fd);
2107
+ try {
2108
+ _fdClose.applySyncPromise(undefined, [fd]);
2109
+ }
2110
+ catch (e) {
2111
+ const msg = e?.message ?? String(e);
2112
+ if (msg.includes("EBADF"))
2113
+ throw createFsError("EBADF", "EBADF: bad file descriptor, close", "close");
2114
+ throw e;
2115
+ }
2116
+ },
2117
+ readSync(fd, buffer, offset, length, position) {
2118
+ const normalized = normalizeReadSyncArgs(buffer, offset, length, position);
2119
+ let base64;
2120
+ try {
2121
+ base64 = _fdRead.applySyncPromise(undefined, [fd, normalized.length, normalized.position ?? null]);
2122
+ }
2123
+ catch (e) {
2124
+ const msg = e?.message ?? String(e);
2125
+ if (msg.includes("EBADF"))
2126
+ throw createFsError("EBADF", msg, "read");
2127
+ throw e;
2128
+ }
2129
+ const bytes = Buffer.from(base64, "base64");
2130
+ const targetBuffer = new Uint8Array(normalized.buffer.buffer, normalized.buffer.byteOffset, normalized.buffer.byteLength);
2131
+ for (let i = 0; i < bytes.length && i < normalized.length; i++) {
2132
+ targetBuffer[normalized.offset + i] = bytes[i];
2133
+ }
2134
+ return bytes.length;
2135
+ },
2136
+ writeSync(fd, buffer, offsetOrPosition, lengthOrEncoding, position) {
2137
+ const normalized = normalizeWriteSyncArgs(buffer, offsetOrPosition, lengthOrEncoding, position);
2138
+ let dataBytes;
2139
+ if (typeof normalized.buffer === "string") {
2140
+ dataBytes = Buffer.from(normalized.buffer, normalized.encoding);
2141
+ }
2142
+ else {
2143
+ dataBytes = new Uint8Array(normalized.buffer.buffer, normalized.buffer.byteOffset + normalized.offset, normalized.length);
2144
+ }
2145
+ const base64 = Buffer.from(dataBytes).toString("base64");
2146
+ const pos = normalized.position ?? null;
2147
+ try {
2148
+ return _fdWrite.applySyncPromise(undefined, [fd, base64, pos]);
2149
+ }
2150
+ catch (e) {
2151
+ const msg = e?.message ?? String(e);
2152
+ if (msg.includes("EBADF"))
2153
+ throw createFsError("EBADF", msg, "write");
2154
+ throw e;
2155
+ }
2156
+ },
2157
+ fstatSync(fd) {
2158
+ normalizeFdInteger(fd);
2159
+ let raw;
2160
+ try {
2161
+ raw = _fdFstat.applySyncPromise(undefined, [fd]);
2162
+ }
2163
+ catch (e) {
2164
+ const msg = e?.message ?? String(e);
2165
+ if (msg.includes("EBADF"))
2166
+ throw createFsError("EBADF", "EBADF: bad file descriptor, fstat", "fstat");
2167
+ throw e;
2168
+ }
2169
+ return new Stats(JSON.parse(raw));
2170
+ },
2171
+ ftruncateSync(fd, len) {
2172
+ normalizeFdInteger(fd);
2173
+ try {
2174
+ _fdFtruncate.applySyncPromise(undefined, [fd, len]);
2175
+ }
2176
+ catch (e) {
2177
+ const msg = e?.message ?? String(e);
2178
+ if (msg.includes("EBADF"))
2179
+ throw createFsError("EBADF", "EBADF: bad file descriptor, ftruncate", "ftruncate");
2180
+ throw e;
2181
+ }
2182
+ },
2183
+ // fsync / fdatasync — no-op for in-memory VFS (validates FD exists)
2184
+ fsyncSync(fd) {
2185
+ normalizeFdInteger(fd);
2186
+ try {
2187
+ _fdFsync.applySyncPromise(undefined, [fd]);
2188
+ }
2189
+ catch (e) {
2190
+ const msg = e?.message ?? String(e);
2191
+ if (msg.includes("EBADF"))
2192
+ throw createFsError("EBADF", "EBADF: bad file descriptor, fsync", "fsync");
2193
+ throw e;
2194
+ }
2195
+ },
2196
+ fdatasyncSync(fd) {
2197
+ normalizeFdInteger(fd);
2198
+ try {
2199
+ _fdFsync.applySyncPromise(undefined, [fd]);
2200
+ }
2201
+ catch (e) {
2202
+ const msg = e?.message ?? String(e);
2203
+ if (msg.includes("EBADF"))
2204
+ throw createFsError("EBADF", "EBADF: bad file descriptor, fdatasync", "fdatasync");
2205
+ throw e;
2206
+ }
2207
+ },
2208
+ // readv — scatter-read into multiple buffers (delegates to readSync)
2209
+ readvSync(fd, buffers, position) {
2210
+ const normalizedFd = normalizeFdInteger(fd);
2211
+ const normalizedBuffers = normalizeIoVectorBuffers(buffers);
2212
+ let totalBytesRead = 0;
2213
+ const normalizedPosition = normalizeOptionalPosition(position);
2214
+ let nextPosition = normalizedPosition;
2215
+ for (const buffer of normalizedBuffers) {
2216
+ const target = buffer instanceof Uint8Array
2217
+ ? buffer
2218
+ : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2219
+ const bytesRead = fs.readSync(normalizedFd, target, 0, target.byteLength, nextPosition);
2220
+ totalBytesRead += bytesRead;
2221
+ if (nextPosition !== null) {
2222
+ nextPosition += bytesRead;
2223
+ }
2224
+ // EOF — stop filling further buffers
2225
+ if (bytesRead < target.byteLength)
2226
+ break;
2227
+ }
2228
+ return totalBytesRead;
2229
+ },
2230
+ // statfs — return synthetic filesystem stats for the in-memory VFS
2231
+ statfsSync(path, _options) {
2232
+ const pathStr = normalizePathLike(path);
2233
+ // Verify path exists
2234
+ if (!fs.existsSync(pathStr)) {
2235
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, statfs '${pathStr}'`, "statfs", pathStr);
2236
+ }
2237
+ // Return synthetic stats — in-memory VFS has no real block device
2238
+ return {
2239
+ type: 0x01021997, // TMPFS_MAGIC
2240
+ bsize: 4096,
2241
+ blocks: 262144, // 1GB virtual capacity
2242
+ bfree: 262144,
2243
+ bavail: 262144,
2244
+ files: 1000000,
2245
+ ffree: 999999,
2246
+ };
2247
+ },
2248
+ // glob — pattern matching over VFS files
2249
+ globSync(pattern, _options) {
2250
+ const patterns = Array.isArray(pattern) ? pattern : [pattern];
2251
+ const results = [];
2252
+ for (const pat of patterns) {
2253
+ _globCollect(pat, results);
2254
+ }
2255
+ return [...new Set(results)].sort();
2256
+ },
2257
+ // Metadata and link sync methods — delegate to VFS via host refs
2258
+ chmodSync(path, mode) {
2259
+ const pathStr = normalizePathLike(path);
2260
+ const modeNum = normalizeModeArgument(mode);
2261
+ bridgeCall(() => _fs.chmod.applySyncPromise(undefined, [pathStr, modeNum]), "chmod", pathStr);
2262
+ },
2263
+ chownSync(path, uid, gid) {
2264
+ const pathStr = normalizePathLike(path);
2265
+ const normalizedUid = normalizeNumberArgument("uid", uid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
2266
+ const normalizedGid = normalizeNumberArgument("gid", gid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
2267
+ bridgeCall(() => _fs.chown.applySyncPromise(undefined, [pathStr, normalizedUid, normalizedGid]), "chown", pathStr);
2268
+ },
2269
+ fchmodSync(fd, mode) {
2270
+ const normalizedFd = normalizeFdInteger(fd);
2271
+ const pathStr = _fdGetPath.applySync(undefined, [normalizedFd]);
2272
+ if (!pathStr) {
2273
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "chmod");
2274
+ }
2275
+ fs.chmodSync(pathStr, normalizeModeArgument(mode));
2276
+ },
2277
+ fchownSync(fd, uid, gid) {
2278
+ const normalizedFd = normalizeFdInteger(fd);
2279
+ const pathStr = _fdGetPath.applySync(undefined, [normalizedFd]);
2280
+ if (!pathStr) {
2281
+ throw createFsError("EBADF", "EBADF: bad file descriptor", "chown");
2282
+ }
2283
+ fs.chownSync(pathStr, uid, gid);
2284
+ },
2285
+ lchownSync(path, uid, gid) {
2286
+ const pathStr = normalizePathLike(path);
2287
+ const normalizedUid = normalizeNumberArgument("uid", uid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
2288
+ const normalizedGid = normalizeNumberArgument("gid", gid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
2289
+ bridgeCall(() => _fs.chown.applySyncPromise(undefined, [pathStr, normalizedUid, normalizedGid]), "chown", pathStr);
2290
+ },
2291
+ linkSync(existingPath, newPath) {
2292
+ const existingStr = normalizePathLike(existingPath, "existingPath");
2293
+ const newStr = normalizePathLike(newPath, "newPath");
2294
+ bridgeCall(() => _fs.link.applySyncPromise(undefined, [existingStr, newStr]), "link", newStr);
2295
+ },
2296
+ symlinkSync(target, path, _type) {
2297
+ const targetStr = normalizePathLike(target, "target");
2298
+ const pathStr = normalizePathLike(path);
2299
+ bridgeCall(() => _fs.symlink.applySyncPromise(undefined, [targetStr, pathStr]), "symlink", pathStr);
2300
+ },
2301
+ readlinkSync(path, _options) {
2302
+ validateEncodingOption(_options);
2303
+ const pathStr = normalizePathLike(path);
2304
+ return bridgeCall(() => _fs.readlink.applySyncPromise(undefined, [pathStr]), "readlink", pathStr);
2305
+ },
2306
+ truncateSync(path, len) {
2307
+ const pathStr = normalizePathLike(path);
2308
+ bridgeCall(() => _fs.truncate.applySyncPromise(undefined, [pathStr, len ?? 0]), "truncate", pathStr);
2309
+ },
2310
+ utimesSync(path, atime, mtime) {
2311
+ const pathStr = normalizePathLike(path);
2312
+ const atimeNum = typeof atime === "number" ? atime : new Date(atime).getTime() / 1000;
2313
+ const mtimeNum = typeof mtime === "number" ? mtime : new Date(mtime).getTime() / 1000;
2314
+ bridgeCall(() => _fs.utimes.applySyncPromise(undefined, [pathStr, atimeNum, mtimeNum]), "utimes", pathStr);
2315
+ },
2316
+ // Async methods - wrap sync methods in callbacks/promises
2317
+ //
2318
+ // IMPORTANT: Low-level fd operations (open, close, read, write) and operations commonly
2319
+ // used by streaming libraries (stat, lstat, rename, unlink) must defer their callbacks
2320
+ // using queueMicrotask(). This is critical for proper stream operation.
2321
+ //
2322
+ // Why: Node.js streams (like tar, minipass, fs-minipass) use callback chains where each
2323
+ // callback triggers the next read/write operation. These streams also rely on events like
2324
+ // 'drain' to know when to resume writing. If callbacks fire synchronously, the event loop
2325
+ // never gets a chance to process these events, causing streams to stall after the first chunk.
2326
+ //
2327
+ // Example problem without queueMicrotask:
2328
+ // 1. tar calls fs.read() with callback
2329
+ // 2. Our sync implementation calls callback immediately
2330
+ // 3. Callback writes to stream, stream buffer fills, returns false (needs drain)
2331
+ // 4. Code sets up 'drain' listener and returns
2332
+ // 5. But we never returned to event loop, so 'drain' never fires
2333
+ // 6. Stream hangs forever
2334
+ //
2335
+ // With queueMicrotask, step 2 defers the callback, allowing the event loop to process
2336
+ // pending events (including 'drain') before the next operation starts.
2337
+ readFile(path, options, callback) {
2338
+ if (typeof options === "function") {
2339
+ callback = options;
2340
+ options = undefined;
2341
+ }
2342
+ if (callback) {
2343
+ normalizePathLike(path);
2344
+ validateEncodingOption(options);
2345
+ try {
2346
+ callback(null, fs.readFileSync(path, options));
2347
+ }
2348
+ catch (e) {
2349
+ callback(e);
2350
+ }
2351
+ }
2352
+ else {
2353
+ return Promise.resolve(fs.readFileSync(path, options));
2354
+ }
2355
+ },
2356
+ writeFile(path, data, options, callback) {
2357
+ if (typeof options === "function") {
2358
+ callback = options;
2359
+ options = undefined;
2360
+ }
2361
+ if (callback) {
2362
+ normalizePathLike(path);
2363
+ validateEncodingOption(options);
2364
+ try {
2365
+ fs.writeFileSync(path, data, options);
2366
+ callback(null);
2367
+ }
2368
+ catch (e) {
2369
+ callback(e);
2370
+ }
2371
+ }
2372
+ else {
2373
+ return Promise.resolve(fs.writeFileSync(path, data, options));
2374
+ }
2375
+ },
2376
+ appendFile(path, data, options, callback) {
2377
+ if (typeof options === "function") {
2378
+ callback = options;
2379
+ options = undefined;
2380
+ }
2381
+ if (callback) {
2382
+ normalizePathLike(path);
2383
+ validateEncodingOption(options);
2384
+ try {
2385
+ fs.appendFileSync(path, data, options);
2386
+ callback(null);
2387
+ }
2388
+ catch (e) {
2389
+ callback(e);
2390
+ }
2391
+ }
2392
+ else {
2393
+ return Promise.resolve(fs.appendFileSync(path, data, options));
2394
+ }
2395
+ },
2396
+ readdir(path, options, callback) {
2397
+ if (typeof options === "function") {
2398
+ callback = options;
2399
+ options = undefined;
2400
+ }
2401
+ if (callback) {
2402
+ normalizePathLike(path);
2403
+ validateEncodingOption(options);
2404
+ try {
2405
+ callback(null, fs.readdirSync(path, options));
2406
+ }
2407
+ catch (e) {
2408
+ callback(e);
2409
+ }
2410
+ }
2411
+ else {
2412
+ return Promise.resolve(fs.readdirSync(path, options));
2413
+ }
2414
+ },
2415
+ mkdir(path, options, callback) {
2416
+ if (typeof options === "function") {
2417
+ callback = options;
2418
+ options = undefined;
2419
+ }
2420
+ if (callback) {
2421
+ normalizePathLike(path);
2422
+ try {
2423
+ fs.mkdirSync(path, options);
2424
+ callback(null);
2425
+ }
2426
+ catch (e) {
2427
+ callback(e);
2428
+ }
2429
+ }
2430
+ else {
2431
+ fs.mkdirSync(path, options);
2432
+ return Promise.resolve();
2433
+ }
2434
+ },
2435
+ rmdir(path, callback) {
2436
+ if (callback) {
2437
+ normalizePathLike(path);
2438
+ // Defer callback to next tick to allow event loop to process stream events
2439
+ const cb = callback;
2440
+ try {
2441
+ fs.rmdirSync(path);
2442
+ queueMicrotask(() => cb(null));
2443
+ }
2444
+ catch (e) {
2445
+ queueMicrotask(() => cb(e));
2446
+ }
2447
+ }
2448
+ else {
2449
+ return Promise.resolve(fs.rmdirSync(path));
2450
+ }
2451
+ },
2452
+ // rm - remove files or directories (with recursive support)
2453
+ rm(path, options, callback) {
2454
+ let opts = {};
2455
+ let cb;
2456
+ if (typeof options === "function") {
2457
+ cb = options;
2458
+ }
2459
+ else if (options) {
2460
+ opts = options;
2461
+ cb = callback;
2462
+ }
2463
+ else {
2464
+ cb = callback;
2465
+ }
2466
+ const doRm = () => {
2467
+ try {
2468
+ const stats = fs.statSync(path);
2469
+ if (stats.isDirectory()) {
2470
+ if (opts.recursive) {
2471
+ // Recursively remove directory contents
2472
+ const entries = fs.readdirSync(path);
2473
+ for (const entry of entries) {
2474
+ const entryPath = path.endsWith("/") ? path + entry : path + "/" + entry;
2475
+ const entryStats = fs.statSync(entryPath);
2476
+ if (entryStats.isDirectory()) {
2477
+ fs.rmSync(entryPath, { recursive: true });
2478
+ }
2479
+ else {
2480
+ fs.unlinkSync(entryPath);
2481
+ }
2482
+ }
2483
+ fs.rmdirSync(path);
2484
+ }
2485
+ else {
2486
+ fs.rmdirSync(path);
2487
+ }
2488
+ }
2489
+ else {
2490
+ fs.unlinkSync(path);
2491
+ }
2492
+ }
2493
+ catch (e) {
2494
+ if (opts.force && e.code === "ENOENT") {
2495
+ return; // Ignore ENOENT when force is true
2496
+ }
2497
+ throw e;
2498
+ }
2499
+ };
2500
+ if (cb) {
2501
+ // Defer callback to next tick to allow event loop to process stream events
2502
+ try {
2503
+ doRm();
2504
+ queueMicrotask(() => cb(null));
2505
+ }
2506
+ catch (e) {
2507
+ queueMicrotask(() => cb(e));
2508
+ }
2509
+ }
2510
+ else {
2511
+ doRm();
2512
+ return Promise.resolve();
2513
+ }
2514
+ },
2515
+ exists(path, callback) {
2516
+ validateCallback(callback, "cb");
2517
+ if (path === undefined) {
2518
+ throw createInvalidArgTypeError("path", "of type string or an instance of Buffer or URL", path);
2519
+ }
2520
+ queueMicrotask(() => callback(Boolean(tryNormalizeExistsPath(path) && fs.existsSync(path))));
2521
+ },
2522
+ stat(path, callback) {
2523
+ validateCallback(callback, "cb");
2524
+ normalizePathLike(path);
2525
+ const cb = callback;
2526
+ try {
2527
+ const stats = fs.statSync(path);
2528
+ queueMicrotask(() => cb(null, stats));
2529
+ }
2530
+ catch (e) {
2531
+ queueMicrotask(() => cb(e));
2532
+ }
2533
+ },
2534
+ lstat(path, callback) {
2535
+ if (callback) {
2536
+ // Defer callback to next tick to allow event loop to process stream events
2537
+ const cb = callback;
2538
+ try {
2539
+ const stats = fs.lstatSync(path);
2540
+ queueMicrotask(() => cb(null, stats));
2541
+ }
2542
+ catch (e) {
2543
+ queueMicrotask(() => cb(e));
2544
+ }
2545
+ }
2546
+ else {
2547
+ return Promise.resolve(fs.lstatSync(path));
2548
+ }
2549
+ },
2550
+ unlink(path, callback) {
2551
+ if (callback) {
2552
+ normalizePathLike(path);
2553
+ // Defer callback to next tick to allow event loop to process stream events
2554
+ const cb = callback;
2555
+ try {
2556
+ fs.unlinkSync(path);
2557
+ queueMicrotask(() => cb(null));
2558
+ }
2559
+ catch (e) {
2560
+ queueMicrotask(() => cb(e));
2561
+ }
2562
+ }
2563
+ else {
2564
+ return Promise.resolve(fs.unlinkSync(path));
2565
+ }
2566
+ },
2567
+ rename(oldPath, newPath, callback) {
2568
+ if (callback) {
2569
+ normalizePathLike(oldPath, "oldPath");
2570
+ normalizePathLike(newPath, "newPath");
2571
+ // Defer callback to next tick to allow event loop to process stream events
2572
+ const cb = callback;
2573
+ try {
2574
+ fs.renameSync(oldPath, newPath);
2575
+ queueMicrotask(() => cb(null));
2576
+ }
2577
+ catch (e) {
2578
+ queueMicrotask(() => cb(e));
2579
+ }
2580
+ }
2581
+ else {
2582
+ return Promise.resolve(fs.renameSync(oldPath, newPath));
2583
+ }
2584
+ },
2585
+ copyFile(src, dest, callback) {
2586
+ if (callback) {
2587
+ try {
2588
+ fs.copyFileSync(src, dest);
2589
+ callback(null);
2590
+ }
2591
+ catch (e) {
2592
+ callback(e);
2593
+ }
2594
+ }
2595
+ else {
2596
+ return Promise.resolve(fs.copyFileSync(src, dest));
2597
+ }
2598
+ },
2599
+ cp(src, dest, options, callback) {
2600
+ if (typeof options === "function") {
2601
+ callback = options;
2602
+ options = undefined;
2603
+ }
2604
+ if (callback) {
2605
+ try {
2606
+ fs.cpSync(src, dest, options);
2607
+ callback(null);
2608
+ }
2609
+ catch (e) {
2610
+ callback(e);
2611
+ }
2612
+ }
2613
+ else {
2614
+ return Promise.resolve(fs.cpSync(src, dest, options));
2615
+ }
2616
+ },
2617
+ mkdtemp(prefix, options, callback) {
2618
+ if (typeof options === "function") {
2619
+ callback = options;
2620
+ options = undefined;
2621
+ }
2622
+ validateCallback(callback, "cb");
2623
+ validateEncodingOption(options);
2624
+ try {
2625
+ callback(null, fs.mkdtempSync(prefix, options));
2626
+ }
2627
+ catch (e) {
2628
+ callback(e);
2629
+ }
2630
+ },
2631
+ opendir(path, options, callback) {
2632
+ if (typeof options === "function") {
2633
+ callback = options;
2634
+ options = undefined;
2635
+ }
2636
+ if (callback) {
2637
+ try {
2638
+ callback(null, fs.opendirSync(path, options));
2639
+ }
2640
+ catch (e) {
2641
+ callback(e);
2642
+ }
2643
+ }
2644
+ else {
2645
+ return Promise.resolve(fs.opendirSync(path, options));
2646
+ }
2647
+ },
2648
+ open(path, flags, mode, callback) {
2649
+ let resolvedFlags = "r";
2650
+ let resolvedMode = mode;
2651
+ if (typeof flags === "function") {
2652
+ callback = flags;
2653
+ resolvedMode = undefined;
2654
+ }
2655
+ else {
2656
+ resolvedFlags = flags ?? "r";
2657
+ }
2658
+ if (typeof mode === "function") {
2659
+ callback = mode;
2660
+ resolvedMode = undefined;
2661
+ }
2662
+ validateCallback(callback, "cb");
2663
+ normalizePathLike(path);
2664
+ normalizeOpenModeArgument(resolvedMode);
2665
+ const cb = callback;
2666
+ try {
2667
+ const fd = fs.openSync(path, resolvedFlags, resolvedMode);
2668
+ queueMicrotask(() => cb(null, fd));
2669
+ }
2670
+ catch (e) {
2671
+ queueMicrotask(() => cb(e));
2672
+ }
2673
+ },
2674
+ close(fd, callback) {
2675
+ normalizeFdInteger(fd);
2676
+ validateCallback(callback, "cb");
2677
+ const cb = callback;
2678
+ try {
2679
+ fs.closeSync(fd);
2680
+ queueMicrotask(() => cb(null));
2681
+ }
2682
+ catch (e) {
2683
+ queueMicrotask(() => cb(e));
2684
+ }
2685
+ },
2686
+ read(fd, buffer, offset, length, position, callback) {
2687
+ if (callback) {
2688
+ // Defer callback to next tick to allow event loop to process stream events
2689
+ const cb = callback;
2690
+ try {
2691
+ const bytesRead = fs.readSync(fd, buffer, offset, length, position);
2692
+ queueMicrotask(() => cb(null, bytesRead, buffer));
2693
+ }
2694
+ catch (e) {
2695
+ queueMicrotask(() => cb(e));
2696
+ }
2697
+ }
2698
+ else {
2699
+ return Promise.resolve(fs.readSync(fd, buffer, offset, length, position));
2700
+ }
2701
+ },
2702
+ write(fd, buffer, offset, length, position, callback) {
2703
+ if (typeof offset === "function") {
2704
+ callback = offset;
2705
+ offset = undefined;
2706
+ length = undefined;
2707
+ position = undefined;
2708
+ }
2709
+ else if (typeof length === "function") {
2710
+ callback = length;
2711
+ length = undefined;
2712
+ position = undefined;
2713
+ }
2714
+ else if (typeof position === "function") {
2715
+ callback = position;
2716
+ position = undefined;
2717
+ }
2718
+ if (callback) {
2719
+ const normalized = normalizeWriteSyncArgs(buffer, offset, length, position);
2720
+ // Defer callback to next tick to allow event loop to process stream events
2721
+ const cb = callback;
2722
+ try {
2723
+ const bytesWritten = typeof normalized.buffer === "string"
2724
+ ? _fdWrite.applySyncPromise(undefined, [fd, Buffer.from(normalized.buffer, normalized.encoding).toString("base64"), normalized.position ?? null])
2725
+ : _fdWrite.applySyncPromise(undefined, [
2726
+ fd,
2727
+ Buffer.from(new Uint8Array(normalized.buffer.buffer, normalized.buffer.byteOffset + normalized.offset, normalized.length)).toString("base64"),
2728
+ normalized.position ?? null,
2729
+ ]);
2730
+ queueMicrotask(() => cb(null, bytesWritten));
2731
+ }
2732
+ catch (e) {
2733
+ queueMicrotask(() => cb(e));
2734
+ }
2735
+ }
2736
+ else {
2737
+ return Promise.resolve(fs.writeSync(fd, buffer, offset, length, position));
2738
+ }
2739
+ },
2740
+ // writev - write multiple buffers to a file descriptor
2741
+ writev(fd, buffers, position, callback) {
2742
+ if (typeof position === "function") {
2743
+ callback = position;
2744
+ position = null;
2745
+ }
2746
+ const normalizedFd = normalizeFdInteger(fd);
2747
+ const normalizedBuffers = normalizeIoVectorBuffers(buffers);
2748
+ const normalizedPosition = normalizeOptionalPosition(position);
2749
+ if (callback) {
2750
+ try {
2751
+ const bytesWritten = fs.writevSync(normalizedFd, normalizedBuffers, normalizedPosition);
2752
+ queueMicrotask(() => callback(null, bytesWritten, normalizedBuffers));
2753
+ }
2754
+ catch (e) {
2755
+ queueMicrotask(() => callback(e));
2756
+ }
2757
+ }
2758
+ },
2759
+ writevSync(fd, buffers, position) {
2760
+ const normalizedFd = normalizeFdInteger(fd);
2761
+ const normalizedBuffers = normalizeIoVectorBuffers(buffers);
2762
+ let nextPosition = normalizeOptionalPosition(position);
2763
+ let totalBytesWritten = 0;
2764
+ for (const buffer of normalizedBuffers) {
2765
+ const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2766
+ totalBytesWritten += fs.writeSync(normalizedFd, bytes, 0, bytes.length, nextPosition);
2767
+ if (nextPosition !== null) {
2768
+ nextPosition += bytes.length;
2769
+ }
2770
+ }
2771
+ return totalBytesWritten;
2772
+ },
2773
+ fstat(fd, callback) {
2774
+ if (callback) {
2775
+ try {
2776
+ callback(null, fs.fstatSync(fd));
2777
+ }
2778
+ catch (e) {
2779
+ callback(e);
2780
+ }
2781
+ }
2782
+ else {
2783
+ return Promise.resolve(fs.fstatSync(fd));
2784
+ }
2785
+ },
2786
+ // fsync / fdatasync async callback forms
2787
+ fsync(fd, callback) {
2788
+ normalizeFdInteger(fd);
2789
+ validateCallback(callback, "cb");
2790
+ try {
2791
+ fs.fsyncSync(fd);
2792
+ callback(null);
2793
+ }
2794
+ catch (e) {
2795
+ callback(e);
2796
+ }
2797
+ },
2798
+ fdatasync(fd, callback) {
2799
+ normalizeFdInteger(fd);
2800
+ validateCallback(callback, "cb");
2801
+ try {
2802
+ fs.fdatasyncSync(fd);
2803
+ callback(null);
2804
+ }
2805
+ catch (e) {
2806
+ callback(e);
2807
+ }
2808
+ },
2809
+ // readv async callback form
2810
+ readv(fd, buffers, position, callback) {
2811
+ if (typeof position === "function") {
2812
+ callback = position;
2813
+ position = null;
2814
+ }
2815
+ const normalizedFd = normalizeFdInteger(fd);
2816
+ const normalizedBuffers = normalizeIoVectorBuffers(buffers);
2817
+ const normalizedPosition = normalizeOptionalPosition(position);
2818
+ if (callback) {
2819
+ try {
2820
+ const bytesRead = fs.readvSync(normalizedFd, normalizedBuffers, normalizedPosition);
2821
+ queueMicrotask(() => callback(null, bytesRead, normalizedBuffers));
2822
+ }
2823
+ catch (e) {
2824
+ queueMicrotask(() => callback(e));
2825
+ }
2826
+ }
2827
+ },
2828
+ // statfs async callback form
2829
+ statfs(path, options, callback) {
2830
+ if (typeof options === "function") {
2831
+ callback = options;
2832
+ options = undefined;
2833
+ }
2834
+ if (callback) {
2835
+ try {
2836
+ callback(null, fs.statfsSync(path, options));
2837
+ }
2838
+ catch (e) {
2839
+ callback(e);
2840
+ }
2841
+ }
2842
+ else {
2843
+ return Promise.resolve(fs.statfsSync(path, options));
2844
+ }
2845
+ },
2846
+ // glob async callback form
2847
+ glob(pattern, options, callback) {
2848
+ if (typeof options === "function") {
2849
+ callback = options;
2850
+ options = undefined;
2851
+ }
2852
+ if (callback) {
2853
+ try {
2854
+ callback(null, fs.globSync(pattern, options));
2855
+ }
2856
+ catch (e) {
2857
+ callback(e);
2858
+ }
2859
+ }
2860
+ },
2861
+ // fs.promises API
2862
+ // Note: Using async functions to properly catch sync errors and return rejected promises
2863
+ promises: {
2864
+ async readFile(path, options) {
2865
+ if (path instanceof FileHandle) {
2866
+ return path.readFile(options);
2867
+ }
2868
+ return fs.readFileSync(path, options);
2869
+ },
2870
+ async writeFile(path, data, options) {
2871
+ if (path instanceof FileHandle) {
2872
+ return path.writeFile(data, options);
2873
+ }
2874
+ return fs.writeFileSync(path, data, options);
2875
+ },
2876
+ async appendFile(path, data, options) {
2877
+ if (path instanceof FileHandle) {
2878
+ return path.appendFile(data, options);
2879
+ }
2880
+ return fs.appendFileSync(path, data, options);
2881
+ },
2882
+ async readdir(path, options) {
2883
+ return fs.readdirSync(path, options);
2884
+ },
2885
+ async mkdir(path, options) {
2886
+ return fs.mkdirSync(path, options);
2887
+ },
2888
+ async rmdir(path) {
2889
+ return fs.rmdirSync(path);
2890
+ },
2891
+ async stat(path) {
2892
+ return fs.statSync(path);
2893
+ },
2894
+ async lstat(path) {
2895
+ return fs.lstatSync(path);
2896
+ },
2897
+ async unlink(path) {
2898
+ return fs.unlinkSync(path);
2899
+ },
2900
+ async rename(oldPath, newPath) {
2901
+ return fs.renameSync(oldPath, newPath);
2902
+ },
2903
+ async copyFile(src, dest) {
2904
+ return fs.copyFileSync(src, dest);
2905
+ },
2906
+ async cp(src, dest, options) {
2907
+ return fs.cpSync(src, dest, options);
2908
+ },
2909
+ async mkdtemp(prefix, options) {
2910
+ return fs.mkdtempSync(prefix, options);
2911
+ },
2912
+ async opendir(path, options) {
2913
+ return fs.opendirSync(path, options);
2914
+ },
2915
+ async open(path, flags, mode) {
2916
+ return new FileHandle(fs.openSync(path, flags ?? "r", mode));
2917
+ },
2918
+ async statfs(path, options) {
2919
+ return fs.statfsSync(path, options);
2920
+ },
2921
+ async glob(pattern, _options) {
2922
+ return fs.globSync(pattern, _options);
2923
+ },
2924
+ async access(path) {
2925
+ if (!fs.existsSync(path)) {
2926
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, access '${path}'`, "access", path);
2927
+ }
2928
+ },
2929
+ async rm(path, options) {
2930
+ return fs.rmSync(path, options);
2931
+ },
2932
+ async chmod(path, mode) {
2933
+ return fs.chmodSync(path, mode);
2934
+ },
2935
+ async chown(path, uid, gid) {
2936
+ return fs.chownSync(path, uid, gid);
2937
+ },
2938
+ async lchown(path, uid, gid) {
2939
+ return fs.lchownSync(path, uid, gid);
2940
+ },
2941
+ async link(existingPath, newPath) {
2942
+ return fs.linkSync(existingPath, newPath);
2943
+ },
2944
+ async symlink(target, path) {
2945
+ return fs.symlinkSync(target, path);
2946
+ },
2947
+ async readlink(path) {
2948
+ return fs.readlinkSync(path);
2949
+ },
2950
+ async truncate(path, len) {
2951
+ return fs.truncateSync(path, len);
2952
+ },
2953
+ async utimes(path, atime, mtime) {
2954
+ return fs.utimesSync(path, atime, mtime);
2955
+ },
2956
+ watch(path, options) {
2957
+ return createUnsupportedPromisesWatchIterator(path, options);
2958
+ },
2959
+ },
2960
+ // Compatibility methods
2961
+ accessSync(path) {
2962
+ // existsSync already normalizes the path
2963
+ if (!fs.existsSync(path)) {
2964
+ throw createFsError("ENOENT", `ENOENT: no such file or directory, access '${path}'`, "access", path);
2965
+ }
2966
+ },
2967
+ access(path, mode, callback) {
2968
+ if (typeof mode === "function") {
2969
+ callback = mode;
2970
+ mode = undefined;
2971
+ }
2972
+ if (callback) {
2973
+ try {
2974
+ fs.accessSync(path);
2975
+ callback(null);
2976
+ }
2977
+ catch (e) {
2978
+ callback(e);
2979
+ }
2980
+ }
2981
+ else {
2982
+ return fs.promises.access(path);
2983
+ }
2984
+ },
2985
+ realpathSync: Object.assign(function realpathSync(path, options) {
2986
+ validateEncodingOption(options);
2987
+ // Resolve symlinks by walking each path component via lstat + readlink
2988
+ const MAX_SYMLINK_DEPTH = 40;
2989
+ let symlinksFollowed = 0;
2990
+ const raw = normalizePathLike(path);
2991
+ // Build initial queue: normalize . and .. segments
2992
+ const pending = [];
2993
+ for (const seg of raw.split("/")) {
2994
+ if (!seg || seg === ".")
2995
+ continue;
2996
+ if (seg === "..") {
2997
+ if (pending.length > 0)
2998
+ pending.pop();
2999
+ }
3000
+ else
3001
+ pending.push(seg);
3002
+ }
3003
+ // Walk each component, resolving symlinks via a queue
3004
+ const resolved = [];
3005
+ while (pending.length > 0) {
3006
+ const seg = pending.shift();
3007
+ if (seg === ".")
3008
+ continue;
3009
+ if (seg === "..") {
3010
+ if (resolved.length > 0)
3011
+ resolved.pop();
3012
+ continue;
3013
+ }
3014
+ resolved.push(seg);
3015
+ const currentPath = "/" + resolved.join("/");
3016
+ try {
3017
+ const stat = fs.lstatSync(currentPath);
3018
+ if (stat.isSymbolicLink()) {
3019
+ if (++symlinksFollowed > MAX_SYMLINK_DEPTH) {
3020
+ const err = new Error(`ELOOP: too many levels of symbolic links, realpath '${raw}'`);
3021
+ err.code = "ELOOP";
3022
+ err.syscall = "realpath";
3023
+ err.path = raw;
3024
+ throw err;
3025
+ }
3026
+ const target = fs.readlinkSync(currentPath);
3027
+ // Prepend target segments to pending for re-resolution
3028
+ const targetSegs = target.split("/").filter(Boolean);
3029
+ if (target.startsWith("/")) {
3030
+ // Absolute symlink — restart from root
3031
+ resolved.length = 0;
3032
+ }
3033
+ else {
3034
+ // Relative symlink — drop current component
3035
+ resolved.pop();
3036
+ }
3037
+ // Prepend target segments so they're processed next
3038
+ pending.unshift(...targetSegs);
3039
+ }
3040
+ }
3041
+ catch (e) {
3042
+ const err = e;
3043
+ if (err.code === "ELOOP")
3044
+ throw e;
3045
+ if (err.code === "ENOENT" || err.code === "ENOTDIR") {
3046
+ const enoent = new Error(`ENOENT: no such file or directory, realpath '${raw}'`);
3047
+ enoent.code = "ENOENT";
3048
+ enoent.syscall = "realpath";
3049
+ enoent.path = raw;
3050
+ throw enoent;
3051
+ }
3052
+ break;
3053
+ }
3054
+ }
3055
+ return "/" + resolved.join("/") || "/";
3056
+ }, {
3057
+ native(path, options) {
3058
+ validateEncodingOption(options);
3059
+ return fs.realpathSync(path);
3060
+ }
3061
+ }),
3062
+ realpath: Object.assign(function realpath(path, optionsOrCallback, callback) {
3063
+ let options;
3064
+ if (typeof optionsOrCallback === "function") {
3065
+ callback = optionsOrCallback;
3066
+ }
3067
+ else {
3068
+ options = optionsOrCallback;
3069
+ }
3070
+ if (callback) {
3071
+ validateEncodingOption(options);
3072
+ callback(null, fs.realpathSync(path, options));
3073
+ }
3074
+ else {
3075
+ return Promise.resolve(fs.realpathSync(path, options));
3076
+ }
3077
+ }, {
3078
+ native(path, optionsOrCallback, callback) {
3079
+ let options;
3080
+ if (typeof optionsOrCallback === "function") {
3081
+ callback = optionsOrCallback;
3082
+ }
3083
+ else {
3084
+ options = optionsOrCallback;
3085
+ }
3086
+ if (callback) {
3087
+ validateEncodingOption(options);
3088
+ callback(null, fs.realpathSync.native(path, options));
3089
+ }
3090
+ else {
3091
+ return Promise.resolve(fs.realpathSync.native(path, options));
3092
+ }
3093
+ }
3094
+ }),
3095
+ ReadStream: ReadStreamFactory,
3096
+ WriteStream: WriteStreamFactory,
3097
+ createReadStream: function createReadStream(path, options) {
3098
+ const opts = typeof options === "string" ? { encoding: options } : options;
3099
+ validateEncodingOption(opts);
3100
+ const fd = normalizeStreamFd(opts?.fd);
3101
+ const pathLike = normalizeStreamPath(path, fd);
3102
+ // Use type assertion since our ReadStream has all the methods npm needs
3103
+ // but not all the complex overloaded signatures of the full Node.js interface
3104
+ return new ReadStream(pathLike, opts);
3105
+ },
3106
+ createWriteStream: function createWriteStream(path, options) {
3107
+ const opts = typeof options === "string" ? { encoding: options } : options;
3108
+ validateEncodingOption(opts);
3109
+ validateWriteStreamStartOption((opts ?? {}));
3110
+ const fd = normalizeStreamFd(opts?.fd);
3111
+ const pathLike = normalizeStreamPath(path, fd);
3112
+ // Use type assertion since our WriteStream has all the methods npm needs
3113
+ // but not all the complex overloaded signatures of the full Node.js interface
3114
+ return new WriteStream(pathLike, opts);
3115
+ },
3116
+ // Unsupported fs APIs — watch requires kernel-level inotify, use polling instead
3117
+ watch(..._args) {
3118
+ normalizeWatchArguments(_args[0], _args[1], _args[2]);
3119
+ throw createUnsupportedWatcherError("watch");
3120
+ },
3121
+ watchFile(..._args) {
3122
+ normalizeWatchFileArguments(_args[0], _args[1], _args[2]);
3123
+ throw createUnsupportedWatcherError("watchFile");
3124
+ },
3125
+ unwatchFile(..._args) {
3126
+ normalizePathLike(_args[0]);
3127
+ throw createUnsupportedWatcherError("unwatchFile");
3128
+ },
3129
+ chmod(path, mode, callback) {
3130
+ if (callback) {
3131
+ normalizePathLike(path);
3132
+ normalizeModeArgument(mode);
3133
+ try {
3134
+ fs.chmodSync(path, mode);
3135
+ callback(null);
3136
+ }
3137
+ catch (e) {
3138
+ callback(e);
3139
+ }
3140
+ }
3141
+ else {
3142
+ return Promise.resolve(fs.chmodSync(path, mode));
3143
+ }
3144
+ },
3145
+ chown(path, uid, gid, callback) {
3146
+ if (callback) {
3147
+ normalizePathLike(path);
3148
+ normalizeNumberArgument("uid", uid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3149
+ normalizeNumberArgument("gid", gid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3150
+ try {
3151
+ fs.chownSync(path, uid, gid);
3152
+ callback(null);
3153
+ }
3154
+ catch (e) {
3155
+ callback(e);
3156
+ }
3157
+ }
3158
+ else {
3159
+ return Promise.resolve(fs.chownSync(path, uid, gid));
3160
+ }
3161
+ },
3162
+ fchmod(fd, mode, callback) {
3163
+ if (callback) {
3164
+ normalizeFdInteger(fd);
3165
+ normalizeModeArgument(mode);
3166
+ try {
3167
+ fs.fchmodSync(fd, mode);
3168
+ callback(null);
3169
+ }
3170
+ catch (e) {
3171
+ callback(e);
3172
+ }
3173
+ }
3174
+ else {
3175
+ normalizeFdInteger(fd);
3176
+ normalizeModeArgument(mode);
3177
+ return Promise.resolve(fs.fchmodSync(fd, mode));
3178
+ }
3179
+ },
3180
+ fchown(fd, uid, gid, callback) {
3181
+ if (callback) {
3182
+ normalizeFdInteger(fd);
3183
+ normalizeNumberArgument("uid", uid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3184
+ normalizeNumberArgument("gid", gid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3185
+ try {
3186
+ fs.fchownSync(fd, uid, gid);
3187
+ callback(null);
3188
+ }
3189
+ catch (e) {
3190
+ callback(e);
3191
+ }
3192
+ }
3193
+ else {
3194
+ normalizeFdInteger(fd);
3195
+ normalizeNumberArgument("uid", uid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3196
+ normalizeNumberArgument("gid", gid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3197
+ return Promise.resolve(fs.fchownSync(fd, uid, gid));
3198
+ }
3199
+ },
3200
+ lchown(path, uid, gid, callback) {
3201
+ if (arguments.length >= 4) {
3202
+ validateCallback(callback, "cb");
3203
+ normalizePathLike(path);
3204
+ normalizeNumberArgument("uid", uid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3205
+ normalizeNumberArgument("gid", gid, { min: -1, max: 0xffffffff, allowNegativeOne: true });
3206
+ try {
3207
+ fs.lchownSync(path, uid, gid);
3208
+ callback(null);
3209
+ }
3210
+ catch (e) {
3211
+ callback(e);
3212
+ }
3213
+ }
3214
+ else {
3215
+ return Promise.resolve(fs.lchownSync(path, uid, gid));
3216
+ }
3217
+ },
3218
+ link(existingPath, newPath, callback) {
3219
+ if (callback) {
3220
+ normalizePathLike(existingPath, "existingPath");
3221
+ normalizePathLike(newPath, "newPath");
3222
+ try {
3223
+ fs.linkSync(existingPath, newPath);
3224
+ callback(null);
3225
+ }
3226
+ catch (e) {
3227
+ callback(e);
3228
+ }
3229
+ }
3230
+ else {
3231
+ return Promise.resolve(fs.linkSync(existingPath, newPath));
3232
+ }
3233
+ },
3234
+ symlink(target, path, typeOrCb, callback) {
3235
+ if (typeof typeOrCb === "function") {
3236
+ callback = typeOrCb;
3237
+ }
3238
+ if (callback) {
3239
+ try {
3240
+ fs.symlinkSync(target, path);
3241
+ callback(null);
3242
+ }
3243
+ catch (e) {
3244
+ callback(e);
3245
+ }
3246
+ }
3247
+ else {
3248
+ return Promise.resolve(fs.symlinkSync(target, path));
3249
+ }
3250
+ },
3251
+ readlink(path, optionsOrCb, callback) {
3252
+ if (typeof optionsOrCb === "function") {
3253
+ callback = optionsOrCb;
3254
+ optionsOrCb = undefined;
3255
+ }
3256
+ if (callback) {
3257
+ normalizePathLike(path);
3258
+ validateEncodingOption(optionsOrCb);
3259
+ try {
3260
+ callback(null, fs.readlinkSync(path, optionsOrCb));
3261
+ }
3262
+ catch (e) {
3263
+ callback(e);
3264
+ }
3265
+ }
3266
+ else {
3267
+ return Promise.resolve(fs.readlinkSync(path, optionsOrCb));
3268
+ }
3269
+ },
3270
+ truncate(path, lenOrCb, callback) {
3271
+ if (typeof lenOrCb === "function") {
3272
+ callback = lenOrCb;
3273
+ lenOrCb = 0;
3274
+ }
3275
+ if (callback) {
3276
+ try {
3277
+ fs.truncateSync(path, lenOrCb);
3278
+ callback(null);
3279
+ }
3280
+ catch (e) {
3281
+ callback(e);
3282
+ }
3283
+ }
3284
+ else {
3285
+ return Promise.resolve(fs.truncateSync(path, lenOrCb));
3286
+ }
3287
+ },
3288
+ utimes(path, atime, mtime, callback) {
3289
+ if (callback) {
3290
+ try {
3291
+ fs.utimesSync(path, atime, mtime);
3292
+ callback(null);
3293
+ }
3294
+ catch (e) {
3295
+ callback(e);
3296
+ }
3297
+ }
3298
+ else {
3299
+ return Promise.resolve(fs.utimesSync(path, atime, mtime));
3300
+ }
3301
+ },
3302
+ };
3303
+ // Wire late-bound glob helpers to the fs object
3304
+ _globReadDir = (dir) => fs.readdirSync(dir);
3305
+ _globStat = (path) => fs.statSync(path);
3306
+ // Export the fs module
3307
+ export default fs;