mirror of
https://github.com/Nystik-gh/ignis.git
synced 2026-06-17 04:35:53 +00:00
154 lines
3.2 KiB
JavaScript
154 lines
3.2 KiB
JavaScript
|
|
// File descriptor shim - maps fake integer fds to in-memory file buffers.
|
||
|
|
// Enables libraries like yauzl that use fs.open/fs.read/fs.close to seek
|
||
|
|
// around files without loading them via readFileSync upfront.
|
||
|
|
|
||
|
|
let nextFd = 100;
|
||
|
|
const openFiles = new Map();
|
||
|
|
|
||
|
|
export function createFdOps(metadataCache, contentCache, transport) {
|
||
|
|
function ensureData(path) {
|
||
|
|
const cached = contentCache.get(path);
|
||
|
|
|
||
|
|
if (cached !== null) {
|
||
|
|
if (typeof cached === "string") {
|
||
|
|
return new TextEncoder().encode(cached);
|
||
|
|
}
|
||
|
|
|
||
|
|
return cached;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Synchronous fetch fallback
|
||
|
|
console.warn("[shim:fs] fd open cache miss, using sync XHR:", path);
|
||
|
|
const data = transport.readFileSync(path);
|
||
|
|
contentCache.set(path, data);
|
||
|
|
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getEntry(fd) {
|
||
|
|
const entry = openFiles.get(fd);
|
||
|
|
|
||
|
|
if (!entry) {
|
||
|
|
const err = new Error(`EBADF: bad file descriptor, fd ${fd}`);
|
||
|
|
err.code = "EBADF";
|
||
|
|
throw err;
|
||
|
|
}
|
||
|
|
|
||
|
|
return entry;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Sync ---
|
||
|
|
|
||
|
|
function openSync(path, flags, mode) {
|
||
|
|
if (!metadataCache.has(path)) {
|
||
|
|
const err = new Error(
|
||
|
|
`ENOENT: no such file or directory, open '${path}'`,
|
||
|
|
);
|
||
|
|
err.code = "ENOENT";
|
||
|
|
throw err;
|
||
|
|
}
|
||
|
|
|
||
|
|
const data = ensureData(path);
|
||
|
|
const fd = nextFd++;
|
||
|
|
openFiles.set(fd, { path, data });
|
||
|
|
|
||
|
|
return fd;
|
||
|
|
}
|
||
|
|
|
||
|
|
function readSync(fd, buffer, offset, length, position) {
|
||
|
|
const entry = getEntry(fd);
|
||
|
|
const available = Math.min(length, entry.data.length - position);
|
||
|
|
|
||
|
|
if (available <= 0) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const slice = entry.data.subarray(position, position + available);
|
||
|
|
buffer.set(slice, offset);
|
||
|
|
|
||
|
|
return available;
|
||
|
|
}
|
||
|
|
|
||
|
|
function closeSync(fd) {
|
||
|
|
openFiles.delete(fd);
|
||
|
|
}
|
||
|
|
|
||
|
|
function fstatSync(fd) {
|
||
|
|
const entry = getEntry(fd);
|
||
|
|
const stat = metadataCache.toStat(entry.path);
|
||
|
|
|
||
|
|
if (stat) {
|
||
|
|
return stat;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fallback: construct minimal stat from the buffer
|
||
|
|
return {
|
||
|
|
size: entry.data.length,
|
||
|
|
isFile: () => true,
|
||
|
|
isDirectory: () => false,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Async (callback style) ---
|
||
|
|
|
||
|
|
function open(path, flags, modeOrCb, cb) {
|
||
|
|
if (typeof modeOrCb === "function") {
|
||
|
|
cb = modeOrCb;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const fd = openSync(path, flags);
|
||
|
|
queueMicrotask(() => cb(null, fd));
|
||
|
|
} catch (e) {
|
||
|
|
queueMicrotask(() => cb(e));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function read(fd, buffer, offset, length, position, cb) {
|
||
|
|
try {
|
||
|
|
const bytesRead = readSync(fd, buffer, offset, length, position);
|
||
|
|
queueMicrotask(() => cb(null, bytesRead, buffer));
|
||
|
|
} catch (e) {
|
||
|
|
queueMicrotask(() => cb(e));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function close(fd, cb) {
|
||
|
|
try {
|
||
|
|
closeSync(fd);
|
||
|
|
|
||
|
|
if (cb) {
|
||
|
|
queueMicrotask(() => cb(null));
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
if (cb) {
|
||
|
|
queueMicrotask(() => cb(e));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function fstat(fd, optionsOrCb, cb) {
|
||
|
|
if (typeof optionsOrCb === "function") {
|
||
|
|
cb = optionsOrCb;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const stat = fstatSync(fd);
|
||
|
|
queueMicrotask(() => cb(null, stat));
|
||
|
|
} catch (e) {
|
||
|
|
queueMicrotask(() => cb(e));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
openSync,
|
||
|
|
readSync,
|
||
|
|
closeSync,
|
||
|
|
fstatSync,
|
||
|
|
open,
|
||
|
|
read,
|
||
|
|
close,
|
||
|
|
fstat,
|
||
|
|
};
|
||
|
|
}
|