shim more buffer methods, and fs methods
getting importer plugin to work,
This commit is contained in:
parent
6dd62a15fa
commit
a98afa46f5
10 changed files with 533 additions and 6 deletions
11
package-lock.json
generated
11
package-lock.json
generated
|
|
@ -1,17 +1,18 @@
|
||||||
{
|
{
|
||||||
"name": "ignis",
|
"name": "ignis",
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ignis",
|
"name": "ignis",
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^3.6.0",
|
"chokidar": "^3.6.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.21.0",
|
"express": "^4.21.0",
|
||||||
|
"pako": "^2.1.0",
|
||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -1406,6 +1407,12 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pako": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||||
|
"license": "(MIT AND Zlib)"
|
||||||
|
},
|
||||||
"node_modules/parseurl": {
|
"node_modules/parseurl": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.21.0",
|
"express": "^4.21.0",
|
||||||
|
"pako": "^2.1.0",
|
||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,158 @@ import {
|
||||||
showConfirmDialog,
|
showConfirmDialog,
|
||||||
showPromptDialog,
|
showPromptDialog,
|
||||||
} from "../../../ui/bootstrap.js";
|
} from "../../../ui/bootstrap.js";
|
||||||
|
import { transport } from "../../fs/transport.js";
|
||||||
|
|
||||||
|
const IMPORTS_DIR = ".obsidian/imports";
|
||||||
|
|
||||||
|
let stagedFiles = [];
|
||||||
|
|
||||||
|
function buildAcceptString(filters) {
|
||||||
|
if (!filters || filters.length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const extensions = filters.flatMap((f) => f.extensions || []);
|
||||||
|
|
||||||
|
if (extensions.includes("*")) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return extensions.map((ext) => "." + ext).join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickFiles(accept, multiple) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.multiple = multiple;
|
||||||
|
input.style.display = "none";
|
||||||
|
|
||||||
|
if (accept) {
|
||||||
|
input.accept = accept;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.addEventListener("change", () => {
|
||||||
|
const files = Array.from(input.files || []);
|
||||||
|
input.remove();
|
||||||
|
resolve(files);
|
||||||
|
});
|
||||||
|
|
||||||
|
// User closed the picker without selecting
|
||||||
|
input.addEventListener("cancel", () => {
|
||||||
|
input.remove();
|
||||||
|
resolve([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.appendChild(input);
|
||||||
|
input.click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadToImports(file) {
|
||||||
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
|
const bytes = new Uint8Array(arrayBuffer);
|
||||||
|
const targetPath = IMPORTS_DIR + "/" + file.name;
|
||||||
|
|
||||||
|
await transport.writeFile(targetPath, bytes);
|
||||||
|
|
||||||
|
return "/" + targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startWorkaroundFlow(options) {
|
||||||
|
const properties = options?.properties || [];
|
||||||
|
const multiple = properties.includes("multiSelections");
|
||||||
|
const accept = buildAcceptString(options?.filters);
|
||||||
|
|
||||||
|
const files = await pickFiles(accept, multiple);
|
||||||
|
|
||||||
|
if (files.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const paths = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const vaultPath = await uploadToImports(file);
|
||||||
|
paths.push(vaultPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
stagedFiles = paths;
|
||||||
|
|
||||||
|
const names = paths.map((p) => p.split("/").pop()).join(", ");
|
||||||
|
|
||||||
|
console.log("[shim:dialog] Files staged for next sync call:", paths);
|
||||||
|
|
||||||
|
await showMessageDialog(
|
||||||
|
"Files Ready",
|
||||||
|
`Uploaded: ${names}\n\nPlease retry the action that brought you here. ` +
|
||||||
|
"The files will be provided automatically.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const dialogShim = {
|
export const dialogShim = {
|
||||||
async showOpenDialog(browserWindow, options) {
|
async showOpenDialog(browserWindow, options) {
|
||||||
// TODO: implement custom modal with server-side file listing
|
if (typeof browserWindow === "object" && !options) {
|
||||||
console.log("[shim:dialog] showOpenDialog (stub):", options);
|
options = browserWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
const properties = options?.properties || [];
|
||||||
|
const multiple = properties.includes("multiSelections");
|
||||||
|
const accept = buildAcceptString(options?.filters);
|
||||||
|
|
||||||
|
console.log("[shim:dialog] showOpenDialog - opening browser file picker");
|
||||||
|
|
||||||
|
const files = await pickFiles(accept, multiple);
|
||||||
|
|
||||||
|
if (files.length === 0) {
|
||||||
return { canceled: true, filePaths: [] };
|
return { canceled: true, filePaths: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePaths = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const vaultPath = await uploadToImports(file);
|
||||||
|
filePaths.push(vaultPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[shim:dialog] showOpenDialog - uploaded:", filePaths);
|
||||||
|
return { canceled: false, filePaths };
|
||||||
|
},
|
||||||
|
|
||||||
|
showOpenDialogSync(browserWindow, options) {
|
||||||
|
if (typeof browserWindow === "object" && !options) {
|
||||||
|
options = browserWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If files were staged from a previous workaround, return them immediately
|
||||||
|
if (stagedFiles.length > 0) {
|
||||||
|
const paths = stagedFiles;
|
||||||
|
stagedFiles = [];
|
||||||
|
console.log(
|
||||||
|
"[shim:dialog] showOpenDialogSync - returning staged files:",
|
||||||
|
paths,
|
||||||
|
);
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
"[shim:dialog] showOpenDialogSync requires workaround in browser context",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fire-and-forget: show warning, then optionally start workaround flow
|
||||||
|
showConfirmDialog(
|
||||||
|
"Feature Not Available",
|
||||||
|
"This action requires a native file picker which is not available in the browser.",
|
||||||
|
"A workaround is available: upload your file first, then retry the action. " +
|
||||||
|
"Would you like to proceed?",
|
||||||
|
"Upload File",
|
||||||
|
).then((confirmed) => {
|
||||||
|
if (confirmed) {
|
||||||
|
startWorkaroundFlow(options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
async showSaveDialog(browserWindow, options) {
|
async showSaveDialog(browserWindow, options) {
|
||||||
|
|
|
||||||
153
src/shims/fs/fd.js
Normal file
153
src/shims/fs/fd.js
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { transport } from "./transport.js";
|
||||||
import { createFsPromises } from "./promises.js";
|
import { createFsPromises } from "./promises.js";
|
||||||
import { createFsSync } from "./sync.js";
|
import { createFsSync } from "./sync.js";
|
||||||
import { createFsWatch } from "./watch.js";
|
import { createFsWatch } from "./watch.js";
|
||||||
|
import { createFdOps } from "./fd.js";
|
||||||
import { constants } from "./constants.js";
|
import { constants } from "./constants.js";
|
||||||
|
|
||||||
const metadataCache = new MetadataCache();
|
const metadataCache = new MetadataCache();
|
||||||
|
|
@ -12,6 +13,7 @@ const contentCache = new ContentCache();
|
||||||
const fsPromises = createFsPromises(metadataCache, contentCache, transport);
|
const fsPromises = createFsPromises(metadataCache, contentCache, transport);
|
||||||
const fsSync = createFsSync(metadataCache, contentCache, transport);
|
const fsSync = createFsSync(metadataCache, contentCache, transport);
|
||||||
const fsWatch = createFsWatch(transport);
|
const fsWatch = createFsWatch(transport);
|
||||||
|
const fdOps = createFdOps(metadataCache, contentCache, transport);
|
||||||
|
|
||||||
export const fsShim = {
|
export const fsShim = {
|
||||||
promises: fsPromises,
|
promises: fsPromises,
|
||||||
|
|
@ -24,6 +26,15 @@ export const fsShim = {
|
||||||
statSync: fsSync.statSync,
|
statSync: fsSync.statSync,
|
||||||
readdirSync: fsSync.readdirSync,
|
readdirSync: fsSync.readdirSync,
|
||||||
|
|
||||||
|
open: fdOps.open,
|
||||||
|
openSync: fdOps.openSync,
|
||||||
|
read: fdOps.read,
|
||||||
|
readSync: fdOps.readSync,
|
||||||
|
close: fdOps.close,
|
||||||
|
closeSync: fdOps.closeSync,
|
||||||
|
fstat: fdOps.fstat,
|
||||||
|
fstatSync: fdOps.fstatSync,
|
||||||
|
|
||||||
watch: fsWatch.watch,
|
watch: fsWatch.watch,
|
||||||
constants,
|
constants,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,5 +197,48 @@ export function createFsPromises(metadataCache, contentCache, transport) {
|
||||||
metadataCache.set(path, meta);
|
metadataCache.set(path, meta);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async open(path, flags) {
|
||||||
|
if (!metadataCache.has(path)) {
|
||||||
|
const err = new Error(
|
||||||
|
`ENOENT: no such file or directory, open '${path}'`,
|
||||||
|
);
|
||||||
|
err.code = "ENOENT";
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await this.readFile(path);
|
||||||
|
const fileData =
|
||||||
|
typeof data === "string" ? new TextEncoder().encode(data) : data;
|
||||||
|
|
||||||
|
const fileStat = metadataCache.toStat(path) || {
|
||||||
|
size: fileData.length,
|
||||||
|
isFile: () => true,
|
||||||
|
isDirectory: () => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
async stat() {
|
||||||
|
return fileStat;
|
||||||
|
},
|
||||||
|
|
||||||
|
async read(buffer, offset, length, position) {
|
||||||
|
const available = Math.min(length, fileData.length - position);
|
||||||
|
|
||||||
|
if (available <= 0) {
|
||||||
|
return { bytesRead: 0, buffer };
|
||||||
|
}
|
||||||
|
|
||||||
|
const slice = fileData.subarray(position, position + available);
|
||||||
|
buffer.set(slice, offset);
|
||||||
|
|
||||||
|
return { bytesRead: available, buffer };
|
||||||
|
},
|
||||||
|
|
||||||
|
async close() {
|
||||||
|
// Nothing to clean up - data is in memory
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,18 @@ function installBuffer() {
|
||||||
|
|
||||||
return new Uint8Array(data);
|
return new Uint8Array(data);
|
||||||
},
|
},
|
||||||
|
alloc: function (size, fill, encoding) {
|
||||||
|
const buf = new Uint8Array(size);
|
||||||
|
|
||||||
|
if (fill !== undefined) {
|
||||||
|
buf.fill(typeof fill === "string" ? fill.charCodeAt(0) : fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
},
|
||||||
|
allocUnsafe: function (size) {
|
||||||
|
return new Uint8Array(size);
|
||||||
|
},
|
||||||
concat: function (arrays) {
|
concat: function (arrays) {
|
||||||
const total = arrays.reduce((sum, a) => sum + a.length, 0);
|
const total = arrays.reduce((sum, a) => sum + a.length, 0);
|
||||||
const result = new Uint8Array(total);
|
const result = new Uint8Array(total);
|
||||||
|
|
@ -39,6 +51,20 @@ function installBuffer() {
|
||||||
isBuffer: function (obj) {
|
isBuffer: function (obj) {
|
||||||
return obj instanceof Uint8Array;
|
return obj instanceof Uint8Array;
|
||||||
},
|
},
|
||||||
|
byteLength: function (str, encoding) {
|
||||||
|
return new TextEncoder().encode(str).length;
|
||||||
|
},
|
||||||
|
isEncoding: function (encoding) {
|
||||||
|
return [
|
||||||
|
"utf8",
|
||||||
|
"utf-8",
|
||||||
|
"ascii",
|
||||||
|
"binary",
|
||||||
|
"base64",
|
||||||
|
"hex",
|
||||||
|
"latin1",
|
||||||
|
].includes((encoding || "").toLowerCase());
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
138
src/shims/node/zlib.js
Normal file
138
src/shims/node/zlib.js
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
// Zlib shim using pako for browser-side deflate/inflate/gzip/gunzip.
|
||||||
|
// Implements Node's zlib convenience functions (async callback + sync variants).
|
||||||
|
// Streaming classes (createDeflate, createGzip, etc.) are NOT implemented yet.
|
||||||
|
|
||||||
|
import pako from "pako";
|
||||||
|
|
||||||
|
// --- Constants ---
|
||||||
|
|
||||||
|
export const constants = {
|
||||||
|
Z_NO_FLUSH: 0,
|
||||||
|
Z_PARTIAL_FLUSH: 1,
|
||||||
|
Z_SYNC_FLUSH: 2,
|
||||||
|
Z_FULL_FLUSH: 3,
|
||||||
|
Z_FINISH: 4,
|
||||||
|
Z_BLOCK: 5,
|
||||||
|
Z_TREES: 6,
|
||||||
|
Z_OK: 0,
|
||||||
|
Z_STREAM_END: 1,
|
||||||
|
Z_NEED_DICT: 2,
|
||||||
|
Z_ERRNO: -1,
|
||||||
|
Z_STREAM_ERROR: -2,
|
||||||
|
Z_DATA_ERROR: -3,
|
||||||
|
Z_MEM_ERROR: -4,
|
||||||
|
Z_BUF_ERROR: -5,
|
||||||
|
Z_VERSION_ERROR: -6,
|
||||||
|
Z_NO_COMPRESSION: 0,
|
||||||
|
Z_BEST_SPEED: 1,
|
||||||
|
Z_BEST_COMPRESSION: 9,
|
||||||
|
Z_DEFAULT_COMPRESSION: -1,
|
||||||
|
Z_FILTERED: 1,
|
||||||
|
Z_HUFFMAN_ONLY: 2,
|
||||||
|
Z_RLE: 3,
|
||||||
|
Z_FIXED: 4,
|
||||||
|
Z_DEFAULT_STRATEGY: 0,
|
||||||
|
Z_DEFAULT_WINDOWBITS: 15,
|
||||||
|
Z_DEFAULT_MEMLEVEL: 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Helpers ---
|
||||||
|
|
||||||
|
function toUint8Array(buf) {
|
||||||
|
if (buf instanceof Uint8Array) {
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof buf === "string") {
|
||||||
|
return new TextEncoder().encode(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf instanceof ArrayBuffer) {
|
||||||
|
return new Uint8Array(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArrayBuffer.isView(buf)) {
|
||||||
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Uint8Array(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapAsync(syncFn) {
|
||||||
|
return function (buf, optionsOrCb, cb) {
|
||||||
|
if (typeof optionsOrCb === "function") {
|
||||||
|
cb = optionsOrCb;
|
||||||
|
optionsOrCb = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = syncFn(buf, optionsOrCb || {});
|
||||||
|
|
||||||
|
if (cb) {
|
||||||
|
queueMicrotask(() => cb(null, result));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (cb) {
|
||||||
|
queueMicrotask(() => cb(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Sync functions ---
|
||||||
|
|
||||||
|
export function deflateSync(buf, options) {
|
||||||
|
return pako.deflate(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inflateSync(buf, options) {
|
||||||
|
return pako.inflate(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deflateRawSync(buf, options) {
|
||||||
|
return pako.deflateRaw(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function inflateRawSync(buf, options) {
|
||||||
|
return pako.inflateRaw(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function gzipSync(buf, options) {
|
||||||
|
return pako.gzip(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function gunzipSync(buf, options) {
|
||||||
|
return pako.ungzip(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unzipSync(buf, options) {
|
||||||
|
return pako.ungzip(toUint8Array(buf), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Async functions (callback style) ---
|
||||||
|
|
||||||
|
export const deflate = wrapAsync(deflateSync);
|
||||||
|
export const inflate = wrapAsync(inflateSync);
|
||||||
|
export const deflateRaw = wrapAsync(deflateRawSync);
|
||||||
|
export const inflateRaw = wrapAsync(inflateRawSync);
|
||||||
|
export const gzip = wrapAsync(gzipSync);
|
||||||
|
export const gunzip = wrapAsync(gunzipSync);
|
||||||
|
export const unzip = wrapAsync(unzipSync);
|
||||||
|
|
||||||
|
// --- Streaming stubs (not yet implemented) ---
|
||||||
|
|
||||||
|
function notImplemented(name) {
|
||||||
|
return function () {
|
||||||
|
throw new Error(
|
||||||
|
`zlib.${name}() streaming is not yet implemented. Use the sync/callback variants instead.`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createDeflate = notImplemented("createDeflate");
|
||||||
|
export const createInflate = notImplemented("createInflate");
|
||||||
|
export const createDeflateRaw = notImplemented("createDeflateRaw");
|
||||||
|
export const createInflateRaw = notImplemented("createInflateRaw");
|
||||||
|
export const createGzip = notImplemented("createGzip");
|
||||||
|
export const createGunzip = notImplemented("createGunzip");
|
||||||
|
export const createUnzip = notImplemented("createUnzip");
|
||||||
|
|
@ -9,6 +9,7 @@ import * as eventsShim from "./node/events.js";
|
||||||
import * as osShim from "./node/os.js";
|
import * as osShim from "./node/os.js";
|
||||||
import * as netShim from "./node/net.js";
|
import * as netShim from "./node/net.js";
|
||||||
import * as httpShim from "./node/http.js";
|
import * as httpShim from "./node/http.js";
|
||||||
|
import * as zlibShim from "./node/zlib.js";
|
||||||
import { wrapWithProxy, installDebugHelpers } from "./debug.js";
|
import { wrapWithProxy, installDebugHelpers } from "./debug.js";
|
||||||
|
|
||||||
const rawRegistry = {
|
const rawRegistry = {
|
||||||
|
|
@ -25,6 +26,7 @@ const rawRegistry = {
|
||||||
net: netShim,
|
net: netShim,
|
||||||
http: httpShim,
|
http: httpShim,
|
||||||
https: httpShim,
|
https: httpShim,
|
||||||
|
zlib: zlibShim,
|
||||||
};
|
};
|
||||||
|
|
||||||
const shimRegistry = {};
|
const shimRegistry = {};
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@
|
||||||
let modalRef;
|
let modalRef;
|
||||||
|
|
||||||
function onConfirm() {
|
function onConfirm() {
|
||||||
dispatch("confirm");
|
|
||||||
modalRef.dismiss();
|
modalRef.dismiss();
|
||||||
|
dispatch("confirm");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEscape() {
|
function onEscape() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue