mirror of
https://github.com/oven-sh/bun
synced 2026-02-03 07:28:53 +00:00
Compare commits
1 Commits
ciro/fix-a
...
fs-watch-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57928f7e80 |
156
packages/bun-types/fs.d.ts
vendored
156
packages/bun-types/fs.d.ts
vendored
@@ -4067,6 +4067,162 @@ declare module "fs" {
|
||||
filename: PathLike,
|
||||
listener?: WatchListener<string>,
|
||||
): FSWatcher;
|
||||
|
||||
/**
|
||||
* A successful call to {@link watchFile} will return a new fs.StatWatcher object.
|
||||
* @since 0.7.1
|
||||
*/
|
||||
export interface StatWatcher extends EventEmitter {
|
||||
/**
|
||||
* When called, requests that the Node.js event loop not exit so long as the watcher is active.
|
||||
*
|
||||
* Calling watcher.ref() multiple times will have no effect.
|
||||
*/
|
||||
ref(): this;
|
||||
|
||||
/**
|
||||
* When called, the active watcher will not require the Node.js event loop to remain active.
|
||||
* If there is no other activity keeping the event loop running, the process may exit before
|
||||
* the watcher's callback is invoked.
|
||||
*
|
||||
* Calling watcher.unref() multiple times will have no effect.
|
||||
*/
|
||||
unref(): this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch for changes on `filename`. The callback `listener` will be called each
|
||||
* time the file is accessed.
|
||||
*
|
||||
* The `options` argument may be omitted. If provided, it should be an object. The`options` object may contain a boolean named `persistent` that indicates
|
||||
* whether the process should continue to run as long as files are being watched.
|
||||
* The `options` object may specify an `interval` property indicating how often the
|
||||
* target should be polled in milliseconds.
|
||||
*
|
||||
* The `listener` gets two arguments the current stat object and the previous
|
||||
* stat object:
|
||||
*
|
||||
* ```js
|
||||
* import { watchFile } from "node:fs";
|
||||
*
|
||||
* watchFile("example.txt", (curr, prev) => {
|
||||
* console.log(`the current mtime is: ${curr.mtime}`);
|
||||
* console.log(`the previous mtime was: ${prev.mtime}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* These stat objects are instances of `fs.Stat`. If the `bigint` option is `true`,
|
||||
* the numeric values in these objects are specified as `BigInt`s.
|
||||
*
|
||||
* To be notified when the file was modified, not just accessed, it is necessary
|
||||
* to compare `curr.mtimeMs` and `prev.mtimeMs`.
|
||||
*
|
||||
* When an `fs.watchFile` operation results in an `ENOENT` error, it
|
||||
* will invoke the listener once, with all the fields zeroed (or, for dates, the
|
||||
* Unix Epoch). If the file is created later on, the listener will be called
|
||||
* again, with the latest stat objects. This is a change in functionality since
|
||||
* v0.10.
|
||||
*
|
||||
* Using {@link watch} is more efficient than `fs.watchFile` and`fs.unwatchFile`.
|
||||
* `fs.watch` should be used instead of `fs.watchFile` and`fs.unwatchFile` when possible.
|
||||
*
|
||||
* When a file being watched by `fs.watchFile()` disappears and reappears,
|
||||
* then the contents of `previous` in the second callback event (the file's
|
||||
* reappearance) will be the same as the contents of `previous` in the first
|
||||
* callback event (its disappearance).
|
||||
*
|
||||
* This happens when:
|
||||
*
|
||||
* * the file is deleted, followed by a restore
|
||||
* * the file is renamed and then renamed a second time back to its original name
|
||||
*
|
||||
* @since 0.7.1
|
||||
*/
|
||||
export type WatchFileOptions = {
|
||||
bigint?: boolean;
|
||||
persistent?: boolean;
|
||||
interval?: number;
|
||||
};
|
||||
|
||||
export type StatsListener = (curr: Stats, prev: Stats) => void;
|
||||
export type BigIntStatsListener = (curr: BigIntStats, prev: BigIntStats) => void;
|
||||
|
||||
/**
|
||||
* Watch for changes on `filename`. The callback `listener` will be called each
|
||||
* time the file is accessed.
|
||||
*
|
||||
* The `options` argument may be omitted. If provided, it should be an object. The`options` object may contain a boolean named `persistent` that indicates
|
||||
* whether the process should continue to run as long as files are being watched.
|
||||
* The `options` object may specify an `interval` property indicating how often the
|
||||
* target should be polled in milliseconds.
|
||||
*
|
||||
* The `listener` gets two arguments the current stat object and the previous
|
||||
* stat object:
|
||||
*
|
||||
* ```js
|
||||
* import { watchFile } from "node:fs";
|
||||
*
|
||||
* watchFile("example.txt", (curr, prev) => {
|
||||
* console.log(`the current mtime is: ${curr.mtime}`);
|
||||
* console.log(`the previous mtime was: ${prev.mtime}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* These stat objects are instances of `fs.Stat`. If the `bigint` option is `true`,
|
||||
* the numeric values in these objects are specified as `BigInt`s.
|
||||
*
|
||||
* To be notified when the file was modified, not just accessed, it is necessary
|
||||
* to compare `curr.mtimeMs` and `prev.mtimeMs`.
|
||||
*
|
||||
* When an `fs.watchFile` operation results in an `ENOENT` error, it
|
||||
* will invoke the listener once, with all the fields zeroed (or, for dates, the
|
||||
* Unix Epoch). If the file is created later on, the listener will be called
|
||||
* again, with the latest stat objects. This is a change in functionality since
|
||||
* v0.10.
|
||||
*
|
||||
* Using {@link watch} is more efficient than `fs.watchFile` and`fs.unwatchFile`.
|
||||
* `fs.watch` should be used instead of `fs.watchFile` and`fs.unwatchFile` when possible.
|
||||
*
|
||||
* When a file being watched by `fs.watchFile()` disappears and reappears,
|
||||
* then the contents of `previous` in the second callback event (the file's
|
||||
* reappearance) will be the same as the contents of `previous` in the first
|
||||
* callback event (its disappearance).
|
||||
*
|
||||
* This happens when:
|
||||
*
|
||||
* * the file is deleted, followed by a restore
|
||||
* * the file is renamed and then renamed a second time back to its original name
|
||||
*
|
||||
* @since 0.7.1
|
||||
*/
|
||||
export function watchFile(
|
||||
filename: PathLike,
|
||||
options:
|
||||
| (WatchFileOptions & {
|
||||
bigint?: false | undefined;
|
||||
})
|
||||
| undefined,
|
||||
listener: StatsListener,
|
||||
): StatWatcher;
|
||||
|
||||
export function watchFile(
|
||||
filename: PathLike,
|
||||
options:
|
||||
| (WatchFileOptions & {
|
||||
bigint: true;
|
||||
})
|
||||
| undefined,
|
||||
listener: BigIntStatsListener,
|
||||
): StatWatcher;
|
||||
|
||||
/**
|
||||
* Watch for changes on `filename`. The callback `listener` will be called each time the file is accessed.
|
||||
* @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol.
|
||||
*/
|
||||
export function watchFile(
|
||||
filename: PathLike,
|
||||
listener: StatsListener,
|
||||
): StatWatcher;
|
||||
}
|
||||
|
||||
declare module "node:fs" {
|
||||
|
||||
@@ -3461,6 +3461,7 @@ pub const JSValue = enum(JSValueReprInt) {
|
||||
i8 => @as(i8, @truncate(toInt32(this))),
|
||||
i32 => @as(i32, @truncate(toInt32(this))),
|
||||
i64 => this.toInt64(),
|
||||
f64 => this.asNumber(),
|
||||
bool => this.toBoolean(),
|
||||
else => @compileError("Not implemented yet"),
|
||||
};
|
||||
@@ -3989,6 +3990,10 @@ pub const JSValue = enum(JSValueReprInt) {
|
||||
return FFI.JSVALUE_IS_NUMBER(.{ .asJSValue = this });
|
||||
}
|
||||
|
||||
pub fn isNumeric(this: JSValue) bool {
|
||||
return this.isNumber() or this.isBigInt();
|
||||
}
|
||||
|
||||
pub fn isError(this: JSValue) bool {
|
||||
if (!this.isCell())
|
||||
return false;
|
||||
@@ -5211,15 +5216,21 @@ pub const CallFrame = opaque {
|
||||
var ptr = self.argumentsPtr();
|
||||
return switch (@as(u4, @min(len, max))) {
|
||||
0 => .{ .ptr = undefined, .len = 0 },
|
||||
4 => Arguments(max).init(comptime @min(4, max), ptr),
|
||||
2 => Arguments(max).init(comptime @min(2, max), ptr),
|
||||
6 => Arguments(max).init(comptime @min(6, max), ptr),
|
||||
3 => Arguments(max).init(comptime @min(3, max), ptr),
|
||||
8 => Arguments(max).init(comptime @min(8, max), ptr),
|
||||
5 => Arguments(max).init(comptime @min(5, max), ptr),
|
||||
1 => Arguments(max).init(comptime @min(1, max), ptr),
|
||||
2 => Arguments(max).init(comptime @min(2, max), ptr),
|
||||
3 => Arguments(max).init(comptime @min(3, max), ptr),
|
||||
4 => Arguments(max).init(comptime @min(4, max), ptr),
|
||||
5 => Arguments(max).init(comptime @min(5, max), ptr),
|
||||
6 => Arguments(max).init(comptime @min(6, max), ptr),
|
||||
7 => Arguments(max).init(comptime @min(7, max), ptr),
|
||||
else => unreachable,
|
||||
8 => Arguments(max).init(comptime @min(8, max), ptr),
|
||||
9 => Arguments(max).init(comptime @min(9, max), ptr),
|
||||
10 => Arguments(max).init(comptime @min(10, max), ptr),
|
||||
11 => Arguments(max).init(comptime @min(11, max), ptr),
|
||||
12 => Arguments(max).init(comptime @min(12, max), ptr),
|
||||
13 => Arguments(max).init(comptime @min(13, max), ptr),
|
||||
14 => Arguments(max).init(comptime @min(14, max), ptr),
|
||||
15 => Arguments(max).init(comptime @min(15, max), ptr),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -364,11 +364,6 @@ pub const FSWatcher = struct {
|
||||
}
|
||||
},
|
||||
.directory => {
|
||||
// macOS should use FSEvents for directories
|
||||
if (comptime Environment.isMac) {
|
||||
@panic("Unexpected directory watch");
|
||||
}
|
||||
|
||||
const affected = event.names(changed_files);
|
||||
|
||||
for (affected) |changed_name_| {
|
||||
|
||||
@@ -1302,6 +1302,29 @@ fn StatsDataType(comptime T: type) type {
|
||||
@as(Date, @enumFromInt(@as(u64, @intCast(@max(stat_.birthtime().tv_sec, 0))))),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fromJS(args: []JSC.JSValue) @This() {
|
||||
return @This(){
|
||||
.dev = if (args.len > 0 and args[0].isNumeric()) args[0].to(T) else 0,
|
||||
.ino = if (args.len > 1 and args[1].isNumeric()) args[1].to(T) else 0,
|
||||
.mode = if (args.len > 2 and args[2].isNumeric()) args[2].to(T) else 0,
|
||||
.nlink = if (args.len > 3 and args[3].isNumeric()) args[3].to(T) else 0,
|
||||
.uid = if (args.len > 4 and args[4].isNumeric()) args[4].to(T) else 0,
|
||||
.gid = if (args.len > 5 and args[5].isNumeric()) args[5].to(T) else 0,
|
||||
.rdev = if (args.len > 6 and args[6].isNumeric()) args[6].to(T) else 0,
|
||||
.size = if (args.len > 7 and args[7].isNumeric()) args[7].to(T) else 0,
|
||||
.blksize = if (args.len > 8 and args[8].isNumeric()) args[8].to(T) else 0,
|
||||
.blocks = if (args.len > 9 and args[9].isNumeric()) args[9].to(T) else 0,
|
||||
.atime_ms = if (args.len > 10 and args[10].isNumeric()) args[10].to(f64) else 0,
|
||||
.mtime_ms = if (args.len > 11 and args[11].isNumeric()) args[11].to(f64) else 0,
|
||||
.ctime_ms = if (args.len > 12 and args[12].isNumeric()) args[12].to(f64) else 0,
|
||||
.birthtime_ms = if (args.len > 13 and args[13].isNumeric()) args[13].to(T) else 0,
|
||||
.atime = @as(Date, @enumFromInt(if (args.len > 10 and args[10].isNumeric()) args[10].to(u64) else 0)),
|
||||
.mtime = @as(Date, @enumFromInt(if (args.len > 11 and args[11].isNumeric()) args[11].to(u64) else 0)),
|
||||
.ctime = @as(Date, @enumFromInt(if (args.len > 12 and args[12].isNumeric()) args[12].to(u64) else 0)),
|
||||
.birthtime = @as(Date, @enumFromInt(if (args.len > 13 and args[13].isNumeric()) args[13].to(u64) else 0)),
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1431,10 +1454,26 @@ pub const Stats = union(enum) {
|
||||
return this;
|
||||
}
|
||||
|
||||
pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*Stats {
|
||||
globalThis.throw("Stats is not constructable. use fs.stat()", .{});
|
||||
|
||||
return null;
|
||||
pub fn constructor(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*This {
|
||||
var this = bun.default_allocator.create(Stats) catch unreachable;
|
||||
var arguments = callframe.arguments(15);
|
||||
var args = arguments.ptr[0..arguments.len];
|
||||
if (args.len > 0 and args[0].isBoolean()) {
|
||||
if (args[0].toBoolean()) {
|
||||
this.* = .{
|
||||
.big = StatsDataType(i64).fromJS(args[1..]),
|
||||
};
|
||||
} else {
|
||||
this.* = .{
|
||||
.small = StatsDataType(i32).fromJS(args[1..]),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
this.* = .{
|
||||
.small = StatsDataType(i32).fromJS(args),
|
||||
};
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
comptime {
|
||||
|
||||
@@ -8,6 +8,7 @@ var { direct, isPromise, isCallable } = $lazy("primordials");
|
||||
import promises from "node:fs/promises";
|
||||
export { default as promises } from "node:fs/promises";
|
||||
import * as Stream from "node:stream";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
var fs = Bun.fs();
|
||||
var debug = process.env.DEBUG ? console.log : () => {};
|
||||
@@ -68,6 +69,124 @@ class FSWatcher extends EventEmitter {
|
||||
this.#watcher?.unref();
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {Map<string, Array<[Function, StatWatcher]>>} */
|
||||
const statWatchers = new Map();
|
||||
|
||||
/** @link https://nodejs.org/api/fs.html#class-fsstatwatcher */
|
||||
class StatWatcher extends EventEmitter {
|
||||
#filename;
|
||||
#options;
|
||||
#listener;
|
||||
#watcher;
|
||||
#timer;
|
||||
#stat;
|
||||
|
||||
constructor(filename, options, listener) {
|
||||
super();
|
||||
this.#filename = filename;
|
||||
if (typeof options === "function") {
|
||||
listener = options;
|
||||
options = undefined;
|
||||
} else if (typeof listener !== "function") {
|
||||
listener = () => {};
|
||||
}
|
||||
this.#listener = listener;
|
||||
this.#options = options;
|
||||
const watchKey = resolve(filename);
|
||||
const watchers = statWatchers.get(watchKey);
|
||||
if (watchers === undefined) {
|
||||
statWatchers.set(watchKey, [[this.#listener, this]]);
|
||||
} else {
|
||||
watchers.push([this.#listener, this]);
|
||||
}
|
||||
this.#watch();
|
||||
}
|
||||
|
||||
#watch() {
|
||||
let previous = this.#stat;
|
||||
let current;
|
||||
try {
|
||||
current = this.#stat = fs.statSync(this.#filename);
|
||||
debug("fs.watchFile mtime", current.mtime);
|
||||
|
||||
if (this.#watcher === undefined) {
|
||||
this.#watcher = fs.watch(this.#filename, this.#options, this.#onEvent.bind(this));
|
||||
}
|
||||
} catch (error) {
|
||||
debug("fs.watchFile error", error);
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// When an `fs.watchFile` operation results in an ENOENT error,
|
||||
// it will invoke the listener once, with all the fields zeroed (or, for dates, the Unix Epoch).
|
||||
// If the file is created later on, the listener will be called again, with the latest stat objects.
|
||||
if (previous === undefined) {
|
||||
current = this.#stat = new fs.Stats(this.#options?.bigint === true);
|
||||
this.#listener?.(current, current);
|
||||
}
|
||||
|
||||
if (this.#timer === undefined) {
|
||||
this.#timer = setInterval(
|
||||
this.#watch.bind(this),
|
||||
this.#options?.interval ?? 5007, // libuv default
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (previous !== undefined && previous.mtimeMs !== current.mtimeMs) {
|
||||
this.#listener?.(current, previous);
|
||||
}
|
||||
this.#clear();
|
||||
}
|
||||
|
||||
#onEvent(eventType, filename) {
|
||||
debug("fs.watchFile event", eventType, filename);
|
||||
switch (eventType) {
|
||||
case "close":
|
||||
this.close();
|
||||
break;
|
||||
case "error":
|
||||
this.close();
|
||||
// fallthrough
|
||||
case "rename":
|
||||
case "change":
|
||||
this.#watch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#clear() {
|
||||
if (this.#timer !== undefined) {
|
||||
debug("fs.watchFile clear timer");
|
||||
clearInterval(this.#timer);
|
||||
this.#timer = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
debug("fs.watchFile close");
|
||||
this.#watcher?.close();
|
||||
this.#watcher = undefined;
|
||||
this.#clear();
|
||||
}
|
||||
|
||||
ref() {
|
||||
debug("fs.watchFile ref");
|
||||
this.#watcher?.ref();
|
||||
this.#timer?.ref();
|
||||
return this;
|
||||
}
|
||||
|
||||
unref() {
|
||||
debug("fs.watchFile unref");
|
||||
this.#watcher?.unref();
|
||||
this.#timer?.unref();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export var access = function access(...args) {
|
||||
callbackify(fs.accessSync, args);
|
||||
},
|
||||
@@ -250,6 +369,43 @@ export var access = function access(...args) {
|
||||
Stats = fs.Stats,
|
||||
watch = function watch(path, options, listener) {
|
||||
return new FSWatcher(path, options, listener);
|
||||
},
|
||||
watchFile = function watchFile(path, options, listener) {
|
||||
return new StatWatcher(path, options, listener);
|
||||
},
|
||||
unwatchFile = function unwatchFile(path, listener) {
|
||||
const watchKey = resolve(path);
|
||||
const watchers = statWatchers.get(watchKey);
|
||||
if (watchers === undefined) {
|
||||
return;
|
||||
}
|
||||
if (typeof listener === "function") {
|
||||
const deleted = new Set();
|
||||
for (const [func, watcher] of watchers) {
|
||||
if (listener !== func) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
watcher.close();
|
||||
} finally {
|
||||
deleted.add(watcher);
|
||||
}
|
||||
}
|
||||
const remaining = watchers.filter(([_, watcher]) => !deleted.has(watcher));
|
||||
if (remaining.length) {
|
||||
statWatchers.set(watchKey, remaining);
|
||||
} else {
|
||||
statWatchers.delete(watchKey);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for (const [_, watcher] of watchers) {
|
||||
watcher.close();
|
||||
}
|
||||
} finally {
|
||||
statWatchers.delete(watchKey);
|
||||
}
|
||||
};
|
||||
|
||||
function callbackify(fsFunction, args) {
|
||||
@@ -1102,6 +1258,9 @@ export default {
|
||||
ReadStream,
|
||||
watch,
|
||||
FSWatcher,
|
||||
watchFile,
|
||||
unwatchFile,
|
||||
StatWatcher,
|
||||
writev,
|
||||
writevSync,
|
||||
readv,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {EventEmitter} from "node:events";
|
||||
import promises2 from "node:fs/promises";
|
||||
import {default as default2} from "node:fs/promises";
|
||||
import * as Stream from "node:stream";
|
||||
import {resolve} from "node:path";
|
||||
var callbackify = function(fsFunction, args) {
|
||||
try {
|
||||
const result = fsFunction.apply(fs, args.slice(0, args.length - 1)), callback = args[args.length - 1];
|
||||
@@ -61,6 +62,75 @@ class FSWatcher extends EventEmitter {
|
||||
this.#watcher?.unref();
|
||||
}
|
||||
}
|
||||
var statWatchers = new Map;
|
||||
|
||||
class StatWatcher extends EventEmitter {
|
||||
#filename;
|
||||
#options;
|
||||
#listener;
|
||||
#watcher;
|
||||
#timer;
|
||||
#stat;
|
||||
constructor(filename, options, listener) {
|
||||
super();
|
||||
if (this.#filename = filename, typeof options === "function")
|
||||
listener = options, options = void 0;
|
||||
else if (typeof listener !== "function")
|
||||
listener = () => {
|
||||
};
|
||||
this.#listener = listener, this.#options = options;
|
||||
const watchKey = resolve(filename), watchers = statWatchers.get(watchKey);
|
||||
if (watchers === void 0)
|
||||
statWatchers.set(watchKey, [[this.#listener, this]]);
|
||||
else
|
||||
watchers.push([this.#listener, this]);
|
||||
this.#watch();
|
||||
}
|
||||
#watch() {
|
||||
let previous = this.#stat, current;
|
||||
try {
|
||||
if (current = this.#stat = fs.statSync(this.#filename), debug("fs.watchFile mtime", current.mtime), this.#watcher === void 0)
|
||||
this.#watcher = fs.watch(this.#filename, this.#options, this.#onEvent.bind(this));
|
||||
} catch (error) {
|
||||
if (debug("fs.watchFile error", error), error.code !== "ENOENT")
|
||||
throw error;
|
||||
if (previous === void 0)
|
||||
current = this.#stat = new fs.Stats(this.#options?.bigint === !0), this.#listener?.(current, current);
|
||||
if (this.#timer === void 0)
|
||||
this.#timer = setInterval(this.#watch.bind(this), this.#options?.interval ?? 5007);
|
||||
return;
|
||||
}
|
||||
if (previous !== void 0 && previous.mtimeMs !== current.mtimeMs)
|
||||
this.#listener?.(current, previous);
|
||||
this.#clear();
|
||||
}
|
||||
#onEvent(eventType, filename) {
|
||||
switch (debug("fs.watchFile event", eventType, filename), eventType) {
|
||||
case "close":
|
||||
this.close();
|
||||
break;
|
||||
case "error":
|
||||
this.close();
|
||||
case "rename":
|
||||
case "change":
|
||||
this.#watch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#clear() {
|
||||
if (this.#timer !== void 0)
|
||||
debug("fs.watchFile clear timer"), clearInterval(this.#timer), this.#timer = void 0;
|
||||
}
|
||||
close() {
|
||||
debug("fs.watchFile close"), this.#watcher?.close(), this.#watcher = void 0, this.#clear();
|
||||
}
|
||||
ref() {
|
||||
return debug("fs.watchFile ref"), this.#watcher?.ref(), this.#timer?.ref(), this;
|
||||
}
|
||||
unref() {
|
||||
return debug("fs.watchFile unref"), this.#watcher?.unref(), this.#timer?.unref(), this;
|
||||
}
|
||||
}
|
||||
var access = function access2(...args) {
|
||||
callbackify(fs.accessSync, args);
|
||||
}, appendFile = function appendFile2(...args) {
|
||||
@@ -157,6 +227,36 @@ var access = function access2(...args) {
|
||||
});
|
||||
}, readvSync = fs.readvSync.bind(fs), Dirent = fs.Dirent, Stats = fs.Stats, watch = function watch2(path, options, listener) {
|
||||
return new FSWatcher(path, options, listener);
|
||||
}, watchFile = function watchFile2(path, options, listener) {
|
||||
return new StatWatcher(path, options, listener);
|
||||
}, unwatchFile = function unwatchFile2(path, listener) {
|
||||
const watchKey = resolve(path), watchers = statWatchers.get(watchKey);
|
||||
if (watchers === void 0)
|
||||
return;
|
||||
if (typeof listener === "function") {
|
||||
const deleted = new Set;
|
||||
for (let [func, watcher] of watchers) {
|
||||
if (listener !== func)
|
||||
continue;
|
||||
try {
|
||||
watcher.close();
|
||||
} finally {
|
||||
deleted.add(watcher);
|
||||
}
|
||||
}
|
||||
const remaining = watchers.filter(([_, watcher]) => !deleted.has(watcher));
|
||||
if (remaining.length)
|
||||
statWatchers.set(watchKey, remaining);
|
||||
else
|
||||
statWatchers.delete(watchKey);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for (let [_, watcher] of watchers)
|
||||
watcher.close();
|
||||
} finally {
|
||||
statWatchers.delete(watchKey);
|
||||
}
|
||||
}, readStreamPathFastPathSymbol = Symbol.for("Bun.Node.readStreamPathFastPath"), readStreamSymbol = Symbol.for("Bun.NodeReadStream"), readStreamPathOrFdSymbol = Symbol.for("Bun.NodeReadStreamPathOrFd"), writeStreamSymbol = Symbol.for("Bun.NodeWriteStream"), writeStreamPathFastPathSymbol = Symbol.for("Bun.NodeWriteStreamFastPath"), writeStreamPathFastPathCallSymbol = Symbol.for("Bun.NodeWriteStreamFastPathCall"), kIoDone = Symbol.for("kIoDone"), defaultReadStreamOptions = {
|
||||
file: void 0,
|
||||
fd: void 0,
|
||||
@@ -664,6 +764,9 @@ var fs_default = {
|
||||
ReadStream,
|
||||
watch,
|
||||
FSWatcher,
|
||||
watchFile,
|
||||
unwatchFile,
|
||||
StatWatcher,
|
||||
writev,
|
||||
writevSync,
|
||||
readv,
|
||||
@@ -680,9 +783,11 @@ export {
|
||||
writeFileSync,
|
||||
writeFile,
|
||||
write,
|
||||
watchFile,
|
||||
watch,
|
||||
utimesSync,
|
||||
utimes,
|
||||
unwatchFile,
|
||||
unlinkSync,
|
||||
unlink,
|
||||
truncateSync,
|
||||
|
||||
Reference in New Issue
Block a user