diff options
author | Minteck <nekostarfan@gmail.com> | 2021-08-24 14:41:48 +0200 |
---|---|---|
committer | Minteck <nekostarfan@gmail.com> | 2021-08-24 14:41:48 +0200 |
commit | d25e11bee6ca5ca523884da132d18e1400e077b9 (patch) | |
tree | 8af39fde19f7ed640a60fb397c7edd647dff1c4c /node_modules/nexe/lib/fs/patch.js | |
download | kartik-iridium-d25e11bee6ca5ca523884da132d18e1400e077b9.tar.gz kartik-iridium-d25e11bee6ca5ca523884da132d18e1400e077b9.tar.bz2 kartik-iridium-d25e11bee6ca5ca523884da132d18e1400e077b9.zip |
Initial commit
Diffstat (limited to 'node_modules/nexe/lib/fs/patch.js')
-rw-r--r-- | node_modules/nexe/lib/fs/patch.js | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/node_modules/nexe/lib/fs/patch.js b/node_modules/nexe/lib/fs/patch.js new file mode 100644 index 0000000..14a5a60 --- /dev/null +++ b/node_modules/nexe/lib/fs/patch.js @@ -0,0 +1,372 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +let originalFsMethods = null; +let lazyRestoreFs = () => { }; +// optional Win32 file namespace prefix followed by drive letter and colon +const windowsFullPathRegex = /^(\\{2}\?\\)?([a-zA-Z]):/; +const upcaseDriveLetter = (s) => s.replace(windowsFullPathRegex, (_match, ns, drive) => `${ns || ''}${drive.toUpperCase()}:`); +function shimFs(binary, fs = require('fs')) { + if (originalFsMethods !== null) { + return; + } + originalFsMethods = Object.assign({}, fs); + const { blobPath, resources: manifest } = binary, { resourceStart, stat } = binary.layout, directories = {}, notAFile = '!@#$%^&*', isWin = process.platform.startsWith('win'), isString = (x) => typeof x === 'string' || x instanceof String, noop = () => { }, path = require('path'), winPath = isWin ? upcaseDriveLetter : (s) => s, baseDir = winPath(path.dirname(process.execPath)); + let log = (_) => true; + let loggedManifest = false; + if ((process.env.DEBUG || '').toLowerCase().includes('nexe:require')) { + log = (text) => { + setupManifest(); + if (!loggedManifest) { + process.stderr.write('[nexe] - MANIFEST' + JSON.stringify(manifest, null, 4) + '\n'); + process.stderr.write('[nexe] - DIRECTORIES' + JSON.stringify(directories, null, 4) + '\n'); + loggedManifest = true; + } + return process.stderr.write('[nexe] - ' + text + '\n'); + }; + } + const getKey = function getKey(filepath) { + if (Buffer.isBuffer(filepath)) { + filepath = filepath.toString(); + } + if (!isString(filepath)) { + return notAFile; + } + let key = path.resolve(baseDir, filepath); + return winPath(key); + }; + const statTime = function () { + return { + dev: 0, + ino: 0, + nlink: 0, + rdev: 0, + uid: 123, + gid: 500, + blksize: 4096, + blocks: 0, + atime: new Date(stat.atime), + atimeMs: stat.atime.getTime(), + mtime: new Date(stat.mtime), + mtimeMs: stat.mtime.getTime(), + ctime: new Date(stat.ctime), + ctimMs: stat.ctime.getTime(), + birthtime: new Date(stat.birthtime), + birthtimeMs: stat.birthtime.getTime(), + }; + }; + let BigInt; + try { + BigInt = eval('BigInt'); + } + catch (ignored) { } + const createStat = function (extensions, options) { + const stat = Object.assign(new fs.Stats(), binary.layout.stat, statTime(), extensions); + if (options && options.bigint && BigInt) { + for (const k in stat) { + if (Object.prototype.hasOwnProperty.call(stat, k) && typeof stat[k] === 'number') { + stat[k] = BigInt(stat[k]); + } + } + } + return stat; + }; + const ownStat = function (filepath, options) { + setupManifest(); + const key = getKey(filepath); + if (directories[key]) { + let mode = binary.layout.stat.mode; + mode |= fs.constants.S_IFDIR; + mode &= ~fs.constants.S_IFREG; + return createStat({ mode, size: 0 }, options); + } + if (manifest[key]) { + return createStat({ size: manifest[key][1] }, options); + } + }; + const getStat = function (fn) { + return function stat(filepath, options, callback) { + let stat; + if (typeof options === 'function') { + callback = options; + stat = ownStat(filepath, null); + } + else { + stat = ownStat(filepath, options); + } + if (stat) { + process.nextTick(() => { + callback(null, stat); + }); + } + else { + return originalFsMethods[fn].apply(fs, arguments); + } + }; + }; + function makeLong(filepath) { + return path._makeLong && path._makeLong(filepath); + } + function fileOpts(options) { + return !options ? {} : isString(options) ? { encoding: options } : options; + } + let setupManifest = () => { + Object.keys(manifest).forEach((filepath) => { + const entry = manifest[filepath]; + const absolutePath = getKey(filepath); + const longPath = makeLong(absolutePath); + const normalizedPath = winPath(path.normalize(filepath)); + if (!manifest[absolutePath]) { + manifest[absolutePath] = entry; + } + if (longPath && !manifest[longPath]) { + manifest[longPath] = entry; + } + if (!manifest[normalizedPath]) { + manifest[normalizedPath] = manifest[filepath]; + } + let currentDir = path.dirname(absolutePath); + let prevDir = absolutePath; + while (currentDir !== prevDir) { + directories[currentDir] = directories[currentDir] || {}; + directories[currentDir][path.basename(prevDir)] = true; + const longDir = makeLong(currentDir); + if (longDir && !directories[longDir]) { + directories[longDir] = directories[currentDir]; + } + prevDir = currentDir; + currentDir = path.dirname(currentDir); + } + }); + manifest[notAFile] = false; + directories[notAFile] = false; + setupManifest = noop; + }; + //naive patches intended to work for most use cases + const nfs = { + existsSync: function existsSync(filepath) { + setupManifest(); + const key = getKey(filepath); + if (manifest[key] || directories[key]) { + return true; + } + return originalFsMethods.existsSync.apply(fs, arguments); + }, + realpath: function realpath(filepath, options, cb) { + setupManifest(); + const key = getKey(filepath); + if (isString(filepath) && (manifest[filepath] || manifest[key])) { + return process.nextTick(() => cb(null, filepath)); + } + return originalFsMethods.realpath.call(fs, filepath, options, cb); + }, + realpathSync: function realpathSync(filepath, options) { + setupManifest(); + const key = getKey(filepath); + if (manifest[key]) { + return filepath; + } + return originalFsMethods.realpathSync.call(fs, filepath, options); + }, + readdir: function readdir(filepath, options, callback) { + setupManifest(); + const dir = directories[getKey(filepath)]; + if (dir) { + if ('function' === typeof options) { + callback = options; + options = { encoding: 'utf8' }; + } + process.nextTick(() => callback(null, Object.keys(dir))); + } + else { + return originalFsMethods.readdir.apply(fs, arguments); + } + }, + readdirSync: function readdirSync(filepath, options) { + setupManifest(); + const dir = directories[getKey(filepath)]; + if (dir) { + return Object.keys(dir); + } + return originalFsMethods.readdirSync.apply(fs, arguments); + }, + readFile: function readFile(filepath, options, callback) { + setupManifest(); + const entry = manifest[getKey(filepath)]; + if (!entry) { + return originalFsMethods.readFile.apply(fs, arguments); + } + const [offset, length] = entry; + const resourceOffset = resourceStart + offset; + const encoding = fileOpts(options).encoding; + callback = typeof options === 'function' ? options : callback; + originalFsMethods.open(blobPath, 'r', function (err, fd) { + if (err) + return callback(err, null); + originalFsMethods.read(fd, Buffer.alloc(length), 0, length, resourceOffset, function (error, bytesRead, result) { + if (error) { + return originalFsMethods.close(fd, function () { + callback(error, null); + }); + } + originalFsMethods.close(fd, function (err) { + if (err) { + return callback(err, result); + } + callback(err, encoding ? result.toString(encoding) : result); + }); + }); + }); + }, + createReadStream: function createReadStream(filepath, options) { + setupManifest(); + const entry = manifest[getKey(filepath)]; + if (!entry) { + return originalFsMethods.createReadStream.apply(fs, arguments); + } + const [offset, length] = entry; + const resourceOffset = resourceStart + offset; + const opts = fileOpts(options); + return originalFsMethods.createReadStream(blobPath, Object.assign({}, opts, { + start: resourceOffset, + end: resourceOffset + length - 1, + })); + }, + readFileSync: function readFileSync(filepath, options) { + setupManifest(); + const entry = manifest[getKey(filepath)]; + if (!entry) { + return originalFsMethods.readFileSync.apply(fs, arguments); + } + const [offset, length] = entry; + const resourceOffset = resourceStart + offset; + const encoding = fileOpts(options).encoding; + const fd = originalFsMethods.openSync(process.execPath, 'r'); + const result = Buffer.alloc(length); + originalFsMethods.readSync(fd, result, 0, length, resourceOffset); + originalFsMethods.closeSync(fd); + return encoding ? result.toString(encoding) : result; + }, + statSync: function statSync(filepath, options) { + const stat = ownStat(filepath, options); + if (stat) { + return stat; + } + return originalFsMethods.statSync.apply(fs, arguments); + }, + stat: getStat('stat'), + lstat: getStat('lstat'), + lstatSync: function statSync(filepath, options) { + const stat = ownStat(filepath, options); + if (stat) { + return stat; + } + return originalFsMethods.lstatSync.apply(fs, arguments); + }, + }; + if (typeof fs.exists === 'function') { + nfs.exists = function (filepath, cb) { + cb = cb || noop; + const exists = nfs.existsSync(filepath); + process.nextTick(() => cb(exists)); + }; + } + const patches = process.nexe.patches || {}; + delete process.nexe; + patches.internalModuleReadFile = function (original, ...args) { + setupManifest(); + const filepath = getKey(args[0]); + if (manifest[filepath]) { + log('read (hit) ' + filepath); + return nfs.readFileSync(filepath, 'utf-8'); + } + log('read (miss) ' + filepath); + return original.call(this, ...args); + }; + let returningArray; + patches.internalModuleReadJSON = function (original, ...args) { + if (returningArray == null) + returningArray = Array.isArray(original.call(this, '')); + const res = patches.internalModuleReadFile.call(this, original, ...args); + return returningArray && !Array.isArray(res) + ? [res, /"(main|name|type|exports|imports)"/.test(res)] + : res; + }; + patches.internalModuleStat = function (original, ...args) { + setupManifest(); + const filepath = getKey(args[0]); + if (manifest[filepath]) { + log('stat (hit) ' + filepath + ' ' + 0); + return 0; + } + if (directories[filepath]) { + log('stat dir (hit) ' + filepath + ' ' + 1); + return 1; + } + const res = original.call(this, ...args); + if (res === 0) { + log('stat (miss) ' + filepath + ' ' + res); + } + else if (res === 1) { + log('stat dir (miss) ' + filepath + ' ' + res); + } + else { + log('stat (fail) ' + filepath + ' ' + res); + } + return res; + }; + if (typeof fs.exists === 'function') { + nfs.exists = function (filepath, cb) { + cb = cb || noop; + const exists = nfs.existsSync(filepath); + if (!exists) { + return originalFsMethods.exists(filepath, cb); + } + process.nextTick(() => cb(exists)); + }; + } + if (typeof fs.copyFile === 'function') { + nfs.copyFile = function (filepath, dest, flags, callback) { + setupManifest(); + const entry = manifest[getKey(filepath)]; + if (!entry) { + return originalFsMethods.copyFile.apply(fs, arguments); + } + if (typeof flags === 'function') { + callback = flags; + flags = 0; + } + nfs.readFile(filepath, (err, buffer) => { + if (err) { + return callback(err); + } + originalFsMethods.writeFile(dest, buffer, (err) => { + if (err) { + return callback(err); + } + callback(null); + }); + }); + }; + nfs.copyFileSync = function (filepath, dest) { + setupManifest(); + const entry = manifest[getKey(filepath)]; + if (!entry) { + return originalFsMethods.copyFileSync.apply(fs, arguments); + } + return originalFsMethods.writeFileSync(dest, nfs.readFileSync(filepath)); + }; + } + Object.assign(fs, nfs); + lazyRestoreFs = () => { + Object.keys(nfs).forEach((key) => { + fs[key] = originalFsMethods[key]; + }); + lazyRestoreFs = () => { }; + }; + return true; +} +exports.shimFs = shimFs; +function restoreFs() { + lazyRestoreFs(); +} +exports.restoreFs = restoreFs; |