basant307/AI_Governance_Project
048
1const {AbortError} = require('./error.js');2const {FSReqCallback} = process.binding('fs');3 4/**5 * This is a workaround for getting access to the ReadFileContext6 * prototype, which we need to be able to patch its methods.7 * @return {Object} The prototype.8 */9exports.getReadFileContextPrototype = function () {10 const fs = require('fs');11 const fsBinding = process.binding('fs');12 13 const originalOpen = fsBinding.open;14 15 let proto;16 fsBinding.open = (_path, _flags, _mode, req) => {17 proto = Object.getPrototypeOf(req.context);18 return originalOpen.apply(fsBinding, [_path, _flags, _mode, req]);19 };20 21 fs.readFile('/ignored.txt', () => {});22 23 fsBinding.open = originalOpen;24 25 return proto;26};27 28/**29 * This patches the ReadFileContext prototype to use mocked bindings30 * when available. This entire implementation is more or less fully31 * copied over from Node.js's /lib/internal/fs/read_file_context.js32 *33 * This patch is required to support Node.js v16+, where the ReadFileContext34 * closes directly over the internal fs bindings, and is also eagerly loader.35 *36 * See https://github.com/tschaub/mock-fs/issues/332 for more information.37 * @param {Object} prototype The ReadFileContext prototype object to patch.38 */39exports.patchReadFileContext = function (prototype) {40 const origRead = prototype.read;41 const origClose = prototype.close;42 43 const kReadFileUnknownBufferLength = 64 * 1024;44 const kReadFileBufferLength = 512 * 1024;45 46 function readFileAfterRead(err, bytesRead) {47 const context = this.context;48 49 if (err) {50 return context.close(err);51 }52 context.pos += bytesRead;53 54 if (context.pos === context.size || bytesRead === 0) {55 context.close();56 } else {57 if (context.size === 0) {58 // Unknown size, just read until we don't get bytes.59 const buffer =60 bytesRead === kReadFileUnknownBufferLength61 ? context.buffer62 : context.buffer.slice(0, bytesRead);63 context.buffers.push(buffer);64 }65 context.read();66 }67 }68 69 function readFileAfterClose(err) {70 const context = this.context;71 const callback = context.callback;72 let buffer = null;73 74 if (context.err || err) {75 // This is a simplification from Node.js, where we don't bother merging the errors76 return callback(context.err || err);77 }78 79 try {80 if (context.size === 0) {81 buffer = Buffer.concat(context.buffers, context.pos);82 } else if (context.pos < context.size) {83 buffer = context.buffer.slice(0, context.pos);84 } else {85 buffer = context.buffer;86 }87 88 if (context.encoding) {89 buffer = buffer.toString(context.encoding);90 }91 } catch (err) {92 return callback(err);93 }94 95 callback(null, buffer);96 }97 98 prototype.read = function read() {99 if (!prototype._mockedBinding) {100 return origRead.apply(this, arguments);101 }102 103 let buffer;104 let offset;105 let length;106 107 if (this.signal && this.signal.aborted) {108 return this.close(new AbortError());109 }110 if (this.size === 0) {111 buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength);112 offset = 0;113 length = kReadFileUnknownBufferLength;114 this.buffer = buffer;115 } else {116 buffer = this.buffer;117 offset = this.pos;118 length = Math.min(kReadFileBufferLength, this.size - this.pos);119 }120 121 const req = new FSReqCallback();122 req.oncomplete = readFileAfterRead;123 req.context = this;124 125 // This call and the one in close() is what we want to change, the126 // rest is pretty much the same as Node.js except we don't have access127 // to some of the internal optimizations.128 prototype._mockedBinding.read(this.fd, buffer, offset, length, -1, req);129 };130 131 prototype.close = function close(err) {132 if (!prototype._mockedBinding) {133 return origClose.apply(this, arguments);134 }135 136 if (this.isUserFd) {137 process.nextTick(function tick(context) {138 readFileAfterClose.apply({context}, [null]);139 }, this);140 return;141 }142 143 const req = new FSReqCallback();144 req.oncomplete = readFileAfterClose;145 req.context = this;146 this.err = err;147 148 prototype._mockedBinding.close(this.fd, req);149 };150};151 