aboutsummaryrefslogtreecommitdiff
path: root/src/js/node/fs.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/node/fs.js')
-rw-r--r--src/js/node/fs.js489
1 files changed, 240 insertions, 249 deletions
diff --git a/src/js/node/fs.js b/src/js/node/fs.js
index e3630c461..b4165311f 100644
--- a/src/js/node/fs.js
+++ b/src/js/node/fs.js
@@ -6,6 +6,9 @@ const promises = require("node:fs/promises");
const Stream = require("node:stream");
const { isArrayBufferView } = require("node:util/types");
+var _writeStreamPathFastPathSymbol = Symbol.for("Bun.NodeWriteStreamFastPath");
+var _fs = Symbol.for("#fs");
+
const constants = $processBindingConstants.fs;
var fs = Bun.fs();
@@ -820,302 +823,290 @@ var defaultWriteStreamOptions = {
},
};
-var WriteStreamClass;
-WriteStream = (function (InternalWriteStream) {
- WriteStreamClass = InternalWriteStream;
- Object.defineProperty(WriteStreamClass.prototype, Symbol.toStringTag, {
- value: "WriteStream",
- enumerable: false,
- });
-
- function WriteStream(path, options) {
- return new InternalWriteStream(path, options);
+var WriteStreamClass = (WriteStream = function WriteStream(path, options = defaultWriteStreamOptions) {
+ if (!(this instanceof WriteStream)) {
+ return new WriteStream(path, options);
}
- WriteStream.prototype = InternalWriteStream.prototype;
- return Object.defineProperty(WriteStream, Symbol.hasInstance, {
- value(instance) {
- return instance instanceof InternalWriteStream;
- },
- });
-})(
- class WriteStream extends Stream.NativeWritable {
- constructor(path, options = defaultWriteStreamOptions) {
- if (!options) {
- throw new TypeError("Expected options to be an object");
- }
- var {
- fs = defaultWriteStreamOptions.fs,
- start = defaultWriteStreamOptions.start,
- flags = defaultWriteStreamOptions.flags,
- mode = defaultWriteStreamOptions.mode,
- autoClose = true,
- emitClose = false,
- autoDestroy = autoClose,
- encoding = defaultWriteStreamOptions.encoding,
- fd = defaultWriteStreamOptions.fd,
- pos = defaultWriteStreamOptions.pos,
- } = options;
-
- var tempThis = {};
- if (fd != null) {
- if (typeof fd !== "number") {
- throw new Error("Expected options.fd to be a number");
- }
- tempThis.fd = fd;
- tempThis[writeStreamPathFastPathSymbol] = false;
- } else if (typeof path === "string") {
- if (path.length === 0) {
- throw new TypeError("Expected a non-empty path");
- }
+ if (!options) {
+ throw new TypeError("Expected options to be an object");
+ }
- if (path.startsWith("file:")) {
- path = Bun.fileURLToPath(path);
- }
+ var {
+ fs = defaultWriteStreamOptions.fs,
+ start = defaultWriteStreamOptions.start,
+ flags = defaultWriteStreamOptions.flags,
+ mode = defaultWriteStreamOptions.mode,
+ autoClose = true,
+ emitClose = false,
+ autoDestroy = autoClose,
+ encoding = defaultWriteStreamOptions.encoding,
+ fd = defaultWriteStreamOptions.fd,
+ pos = defaultWriteStreamOptions.pos,
+ } = options;
+
+ var tempThis = {};
+ if (fd != null) {
+ if (typeof fd !== "number") {
+ throw new Error("Expected options.fd to be a number");
+ }
+ tempThis.fd = fd;
+ tempThis[_writeStreamPathFastPathSymbol] = false;
+ } else if (typeof path === "string") {
+ if (path.length === 0) {
+ throw new TypeError("Expected a non-empty path");
+ }
- tempThis.path = path;
- tempThis.fd = null;
- tempThis[writeStreamPathFastPathSymbol] =
- autoClose &&
- (start === undefined || start === 0) &&
- fs.write === defaultWriteStreamOptions.fs.write &&
- fs.close === defaultWriteStreamOptions.fs.close;
- }
+ if (path.startsWith("file:")) {
+ path = Bun.fileURLToPath(path);
+ }
- if (tempThis.fd == null) {
- tempThis.fd = fs.openSync(path, flags, mode);
- }
+ tempThis.path = path;
+ tempThis.fd = null;
+ tempThis[_writeStreamPathFastPathSymbol] =
+ autoClose &&
+ (start === undefined || start === 0) &&
+ fs.write === defaultWriteStreamOptions.fs.write &&
+ fs.close === defaultWriteStreamOptions.fs.close;
+ }
- super(tempThis.fd, {
- ...options,
- decodeStrings: false,
- autoDestroy,
- emitClose,
- fd: tempThis,
- });
- Object.assign(this, tempThis);
+ if (tempThis.fd == null) {
+ tempThis.fd = fs.openSync(path, flags, mode);
+ }
- if (typeof fs?.write !== "function") {
- throw new TypeError("Expected fs.write to be a function");
- }
+ NativeWritable.call(this, tempThis.fd, {
+ ...options,
+ decodeStrings: false,
+ autoDestroy,
+ emitClose,
+ fd: tempThis,
+ });
+ Object.assign(this, tempThis);
- if (typeof fs?.close !== "function") {
- throw new TypeError("Expected fs.close to be a function");
- }
+ if (typeof fs?.write !== "function") {
+ throw new TypeError("Expected fs.write to be a function");
+ }
- if (typeof fs?.open !== "function") {
- throw new TypeError("Expected fs.open to be a function");
- }
+ if (typeof fs?.close !== "function") {
+ throw new TypeError("Expected fs.close to be a function");
+ }
- if (typeof path === "object" && path) {
- if (path instanceof URL) {
- path = Bun.fileURLToPath(path);
- }
- }
+ if (typeof fs?.open !== "function") {
+ throw new TypeError("Expected fs.open to be a function");
+ }
- if (typeof path !== "string" && typeof fd !== "number") {
- throw new TypeError("Expected a path or file descriptor");
- }
+ if (typeof path === "object" && path) {
+ if (path instanceof URL) {
+ path = Bun.fileURLToPath(path);
+ }
+ }
- this.start = start;
- this.#fs = fs;
- this.flags = flags;
- this.mode = mode;
+ if (typeof path !== "string" && typeof fd !== "number") {
+ throw new TypeError("Expected a path or file descriptor");
+ }
- if (this.start !== undefined) {
- this.pos = this.start;
- }
+ this.start = start;
+ this[_fs] = fs;
+ this.flags = flags;
+ this.mode = mode;
+ this.bytesWritten = 0;
+ this[writeStreamSymbol] = true;
+ this[kIoDone] = false;
+ // _write = undefined;
+ // _writev = undefined;
+
+ if (this.start !== undefined) {
+ this.pos = this.start;
+ }
- if (encoding !== defaultWriteStreamOptions.encoding) {
- this.setDefaultEncoding(encoding);
- if (encoding !== "buffer" && encoding !== "utf8" && encoding !== "utf-8" && encoding !== "binary") {
- this[writeStreamPathFastPathSymbol] = false;
- }
- }
+ if (encoding !== defaultWriteStreamOptions.encoding) {
+ this.setDefaultEncoding(encoding);
+ if (encoding !== "buffer" && encoding !== "utf8" && encoding !== "utf-8" && encoding !== "binary") {
+ this[_writeStreamPathFastPathSymbol] = false;
}
+ }
- get autoClose() {
- return this._writableState.autoDestroy;
- }
+ return this;
+});
+const NativeWritable = Stream.NativeWritable;
+const WriteStreamPrototype = (WriteStream.prototype = Object.create(NativeWritable.prototype));
- set autoClose(val) {
+Object.defineProperties(WriteStreamPrototype, {
+ autoClose: {
+ get() {
+ return this._writableState.autoDestroy;
+ },
+ set(val) {
this._writableState.autoDestroy = val;
- }
+ },
+ },
+ pending: {
+ get() {
+ return this.fd === null;
+ },
+ },
+});
- destroySoon = this.end; // TODO: what is this for?
+// TODO: what is this for?
+WriteStreamPrototype.destroySoon = WriteStreamPrototype.end;
- // noop, node has deprecated this
- open() {}
+// noop, node has deprecated this
+WriteStreamPrototype.open = function open() {};
- path;
- fd;
- flags;
- mode;
- #fs;
- bytesWritten = 0;
- pos;
- [writeStreamPathFastPathSymbol];
- [writeStreamSymbol] = true;
- start;
+WriteStreamPrototype[writeStreamPathFastPathCallSymbol] = function WriteStreamPathFastPathCallSymbol(
+ readStream,
+ pipeOpts,
+) {
+ if (!this[_writeStreamPathFastPathSymbol]) {
+ return false;
+ }
- [writeStreamPathFastPathCallSymbol](readStream, pipeOpts) {
- if (!this[writeStreamPathFastPathSymbol]) {
- return false;
- }
+ if (this.fd !== null) {
+ this[_writeStreamPathFastPathSymbol] = false;
+ return false;
+ }
- if (this.fd !== null) {
- this[writeStreamPathFastPathSymbol] = false;
- return false;
- }
+ this[kIoDone] = false;
+ readStream[kIoDone] = false;
+ return Bun.write(this[_writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then(
+ bytesWritten => {
+ readStream[kIoDone] = this[kIoDone] = true;
+ this.bytesWritten += bytesWritten;
+ readStream.bytesRead += bytesWritten;
+ this.end();
+ readStream.close();
+ },
+ err => {
+ readStream[kIoDone] = this[kIoDone] = true;
+ WriteStream_errorOrDestroy.call(this, err);
+ readStream.emit("error", err);
+ },
+ );
+};
- this[kIoDone] = false;
- readStream[kIoDone] = false;
- return Bun.write(this[writeStreamPathFastPathSymbol], readStream[readStreamPathOrFdSymbol]).then(
- bytesWritten => {
- readStream[kIoDone] = this[kIoDone] = true;
- this.bytesWritten += bytesWritten;
- readStream.bytesRead += bytesWritten;
- this.end();
- readStream.close();
- },
- err => {
- readStream[kIoDone] = this[kIoDone] = true;
- this.#errorOrDestroy(err);
- readStream.emit("error", err);
- },
- );
- }
+WriteStreamPrototype.isBunFastPathEnabled = function isBunFastPathEnabled() {
+ return this[_writeStreamPathFastPathSymbol];
+};
- isBunFastPathEnabled() {
- return this[writeStreamPathFastPathSymbol];
- }
+WriteStreamPrototype.disableBunFastPath = function disableBunFastPath() {
+ this[_writeStreamPathFastPathSymbol] = false;
+};
- disableBunFastPath() {
- this[writeStreamPathFastPathSymbol] = false;
- }
+function WriteStream_handleWrite(er, bytes) {
+ if (er) {
+ return WriteStream_errorOrDestroy.call(this, er);
+ }
- #handleWrite(er, bytes) {
- if (er) {
- return this.#errorOrDestroy(er);
- }
+ this.bytesWritten += bytes;
+}
- this.bytesWritten += bytes;
- }
+function WriteStream_internalClose(err, cb) {
+ this[_writeStreamPathFastPathSymbol] = false;
+ var fd = this.fd;
+ this[_fs].close(fd, er => {
+ this.fd = null;
+ cb(err || er);
+ });
+}
- #internalClose(err, cb) {
- this[writeStreamPathFastPathSymbol] = false;
- var fd = this.fd;
- this.#fs.close(fd, er => {
- this.fd = null;
- cb(err || er);
- });
- }
+WriteStreamPrototype._construct = function _construct(callback) {
+ if (typeof this.fd === "number") {
+ callback();
+ return;
+ }
- _construct(callback) {
- if (typeof this.fd === "number") {
- callback();
- return;
- }
+ callback();
+ this.emit("open", this.fd);
+ this.emit("ready");
+};
- callback();
- this.emit("open", this.fd);
- this.emit("ready");
- }
+WriteStreamPrototype._destroy = function _destroy(err, cb) {
+ if (this.fd === null) {
+ return cb(err);
+ }
- _destroy(err, cb) {
- if (this.fd === null) {
- return cb(err);
- }
+ if (this[kIoDone]) {
+ this.once(kIoDone, () => WriteStream_internalClose.call(this, err, cb));
+ return;
+ }
- if (this[kIoDone]) {
- this.once(kIoDone, () => this.#internalClose(err, cb));
- return;
- }
+ WriteStream_internalClose.call(this, err, cb);
+};
- this.#internalClose(err, cb);
+WriteStreamPrototype.close = function close(cb) {
+ if (cb) {
+ if (this.closed) {
+ process.nextTick(cb);
+ return;
}
+ this.on("close", cb);
+ }
- [kIoDone] = false;
-
- close(cb) {
- if (cb) {
- if (this.closed) {
- process.nextTick(cb);
- return;
- }
- this.on("close", cb);
- }
-
- // If we are not autoClosing, we should call
- // destroy on 'finish'.
- if (!this.autoClose) {
- this.on("finish", this.destroy);
- }
+ // If we are not autoClosing, we should call
+ // destroy on 'finish'.
+ if (!this.autoClose) {
+ this.on("finish", this.destroy);
+ }
- // We use end() instead of destroy() because of
- // https://github.com/nodejs/node/issues/2006
- this.end();
- }
+ // We use end() instead of destroy() because of
+ // https://github.com/nodejs/node/issues/2006
+ this.end();
+};
- write(chunk, encoding = this._writableState.defaultEncoding, cb) {
- this[writeStreamPathFastPathSymbol] = false;
- if (typeof chunk === "string") {
- chunk = Buffer.from(chunk, encoding);
- }
+WriteStreamPrototype.write = function write(chunk, encoding, cb) {
+ encoding ??= this._writableState?.defaultEncoding;
+ this[_writeStreamPathFastPathSymbol] = false;
+ if (typeof chunk === "string") {
+ chunk = Buffer.from(chunk, encoding);
+ }
- // TODO: Replace this when something like lseek is available
- var native = this.pos === undefined;
- const callback = native
- ? (err, bytes) => {
- this[kIoDone] = false;
- this.#handleWrite(err, bytes);
- this.emit(kIoDone);
- if (cb) !err ? cb() : cb(err);
- }
- : () => {};
- this[kIoDone] = true;
- if (this._write) {
- return this._write(chunk, encoding, callback);
- } else {
- return super.write(chunk, encoding, callback, native);
+ // TODO: Replace this when something like lseek is available
+ var native = this.pos === undefined;
+ const callback = native
+ ? (err, bytes) => {
+ this[kIoDone] = false;
+ WriteStream_handleWrite.call(this, err, bytes);
+ this.emit(kIoDone);
+ if (cb) !err ? cb() : cb(err);
}
- }
-
- end(chunk, encoding, cb) {
- var native = this.pos === undefined;
- return super.end(chunk, encoding, cb, native);
- }
+ : () => {};
+ this[kIoDone] = true;
+ if (this._write) {
+ return this._write(chunk, encoding, callback);
+ } else {
+ return NativeWritable.prototype.write.call(this, chunk, encoding, callback, native);
+ }
+};
- _write = undefined;
- _writev = undefined;
+// Do not inherit
+WriteStreamPrototype._write = undefined;
+WriteStreamPrototype._writev = undefined;
- get pending() {
- return this.fd === null;
- }
+WriteStreamPrototype.end = function end(chunk, encoding, cb) {
+ var native = this.pos === undefined;
+ return NativeWritable.prototype.end.call(this, chunk, encoding, cb, native);
+};
- _destroy(err, cb) {
- this.close(err, cb);
- }
+WriteStreamPrototype._destroy = function _destroy(err, cb) {
+ this.close(err, cb);
+};
- #errorOrDestroy(err) {
- var {
- _readableState: r = { destroyed: false, autoDestroy: false },
- _writableState: w = { destroyed: false, autoDestroy: false },
- } = this;
+function WriteStream_errorOrDestroy(err) {
+ var {
+ _readableState: r = { destroyed: false, autoDestroy: false },
+ _writableState: w = { destroyed: false, autoDestroy: false },
+ } = this;
- if (w?.destroyed || r?.destroyed) {
- return this;
- }
- if (r?.autoDestroy || w?.autoDestroy) this.destroy(err);
- else if (err) {
- this.emit("error", err);
- }
- }
- },
-);
+ if (w?.destroyed || r?.destroyed) {
+ return this;
+ }
+ if (r?.autoDestroy || w?.autoDestroy) this.destroy(err);
+ else if (err) {
+ this.emit("error", err);
+ }
+}
function createWriteStream(path, options) {
- // const WriteStream = getLazyWriteStream();
return new WriteStream(path, options);
}