move shim to new package

This commit is contained in:
Nystik
2026-05-20 20:49:28 +02:00
parent a0b44bde58
commit fe11f30c01
66 changed files with 46 additions and 23 deletions

View File

@@ -0,0 +1,15 @@
function notAvailable(name) {
return function () {
throw new Error(
`child_process.${name}() is not available in the web version.`,
);
};
}
export const exec = notAvailable("exec");
export const execSync = notAvailable("execSync");
export const spawn = notAvailable("spawn");
export const fork = notAvailable("fork");
export const execFile = notAvailable("execFile");
export const execFileSync = notAvailable("execFileSync");
export const spawnSync = notAvailable("spawnSync");

View File

@@ -0,0 +1,106 @@
export class EventEmitter {
constructor() {
this._events = {};
}
on(event, listener) {
if (!this._events[event]) {
this._events[event] = [];
}
this._events[event].push(listener);
return this;
}
once(event, listener) {
const wrapped = (...args) => {
this.removeListener(event, wrapped);
listener.apply(this, args);
};
wrapped._original = listener;
return this.on(event, wrapped);
}
emit(event, ...args) {
const listeners = this._events[event];
if (!listeners || listeners.length === 0) {
return false;
}
for (const fn of [...listeners]) {
fn.apply(this, args);
}
return true;
}
removeListener(event, listener) {
const arr = this._events[event];
if (!arr) {
return this;
}
const idx = arr.findIndex(
(fn) => fn === listener || fn._original === listener,
);
if (idx >= 0) {
arr.splice(idx, 1);
}
return this;
}
off(event, listener) {
return this.removeListener(event, listener);
}
removeAllListeners(event) {
if (event) {
delete this._events[event];
} else {
this._events = {};
}
return this;
}
listeners(event) {
return (this._events[event] || []).slice();
}
listenerCount(event) {
return (this._events[event] || []).length;
}
addListener(event, listener) {
return this.on(event, listener);
}
prependListener(event, listener) {
if (!this._events[event]) {
this._events[event] = [];
}
this._events[event].unshift(listener);
return this;
}
eventNames() {
return Object.keys(this._events);
}
setMaxListeners() {
return this;
}
getMaxListeners() {
return 10;
}
}
export default EventEmitter;

View File

@@ -0,0 +1,54 @@
// Minimal http/https stub. Plugins needing full http.request won't work,
// but this prevents crashes for plugins that just import the module.
import { EventEmitter } from "./events.js";
export class IncomingMessage extends EventEmitter {
constructor() {
super();
this.headers = {};
this.statusCode = 0;
}
}
export class ClientRequest extends EventEmitter {
constructor() {
super();
}
end() {}
write() {}
abort() {}
destroy() {}
}
export function request(options, callback) {
const req = new ClientRequest();
if (callback) {
req.once("response", callback);
}
// Immediately error. real HTTP requests need fetch or the proxy
setTimeout(() => {
req.emit(
"error",
new Error(
"http.request is not available in the web version. Use requestUrl() instead.",
),
);
}, 0);
return req;
}
export function get(options, callback) {
const req = request(options, callback);
req.end();
return req;
}
export function createServer() {
throw new Error("http.createServer is not available in the web version.");
}
export const Agent = class {};
export const globalAgent = new Agent();

View File

@@ -0,0 +1,19 @@
function notAvailable(name) {
return function () {
throw new Error(`net.${name}() is not available in the web version.`);
};
}
export const createServer = notAvailable("createServer");
export const createConnection = notAvailable("createConnection");
export const connect = notAvailable("connect");
export class Socket {
constructor() {
throw new Error("net.Socket is not available in the web version.");
}
}
export class Server {
constructor() {
throw new Error("net.Server is not available in the web version.");
}
}

View File

@@ -0,0 +1,53 @@
export function platform() {
return "linux";
}
export function arch() {
return "x64";
}
export function homedir() {
return "/";
}
export function tmpdir() {
return "/tmp";
}
export function hostname() {
return "localhost";
}
export function type() {
return "Linux";
}
export function release() {
return "0.0.0";
}
export function cpus() {
return [{ model: "browser", speed: 0 }];
}
export function totalmem() {
return 0;
}
export function freemem() {
return 0;
}
export function networkInterfaces() {
return {};
}
export function endianness() {
return "LE";
}
export function version() {
return "v20.0.0";
}
export const EOL = "\n";

View File

@@ -0,0 +1,163 @@
// Shim for Node's `util` module.
// Implements the most commonly used functions; stubs the rest.
function promisify(fn) {
if (typeof fn !== "function") {
throw new TypeError('The "original" argument must be of type Function');
}
// If the function already has a custom promisified version, use it.
if (fn[promisify.custom]) {
return fn[promisify.custom];
}
function promisified(...args) {
return new Promise((resolve, reject) => {
fn.call(this, ...args, (err, ...results) => {
if (err) {
reject(err);
} else if (results.length <= 1) {
resolve(results[0]);
} else {
resolve(results);
}
});
});
}
return promisified;
}
promisify.custom = Symbol.for("nodejs.util.promisify.custom");
function callbackify(fn) {
if (typeof fn !== "function") {
throw new TypeError('The "original" argument must be of type Function');
}
function callbackified(...args) {
const callback = args.pop();
fn.apply(this, args).then(
(result) => callback(null, result),
(err) => callback(err),
);
}
return callbackified;
}
function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
}
function deprecate(fn, msg) {
let warned = false;
function deprecated(...args) {
if (!warned) {
console.warn("[ignis:util] DeprecationWarning:", msg);
warned = true;
}
return fn.apply(this, args);
}
return deprecated;
}
function inspect(obj, opts) {
try {
return JSON.stringify(obj, null, 2);
} catch {
return String(obj);
}
}
function format(fmt, ...args) {
if (typeof fmt !== "string") {
return [fmt, ...args].map(String).join(" ");
}
let i = 0;
const result = fmt.replace(/%[sdjifoO%]/g, (match) => {
if (match === "%%") {
return "%";
}
if (i >= args.length) {
return match;
}
const arg = args[i++];
switch (match) {
case "%s":
return String(arg);
case "%d":
case "%i":
return parseInt(arg, 10).toString();
case "%f":
return parseFloat(arg).toString();
case "%j":
try {
return JSON.stringify(arg);
} catch {
return "[Circular]";
}
case "%o":
case "%O":
return inspect(arg);
default:
return match;
}
});
// Append remaining args.
const remaining = args.slice(i);
if (remaining.length > 0) {
return result + " " + remaining.map(String).join(" ");
}
return result;
}
function debuglog(section) {
return function () {};
}
function isDeepStrictEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
const types = {
isArray: Array.isArray,
isDate: (v) => v instanceof Date,
isRegExp: (v) => v instanceof RegExp,
isAsyncFunction: (v) => typeof v === "function" && v.constructor.name === "AsyncFunction",
isPromise: (v) => v instanceof Promise,
isGeneratorFunction: (v) => typeof v === "function" && v.constructor.name === "GeneratorFunction",
isArrayBuffer: (v) => v instanceof ArrayBuffer,
isTypedArray: (v) => ArrayBuffer.isView(v) && !(v instanceof DataView),
isMap: (v) => v instanceof Map,
isSet: (v) => v instanceof Set,
isWeakMap: (v) => v instanceof WeakMap,
isWeakSet: (v) => v instanceof WeakSet,
};
module.exports = {
promisify,
callbackify,
inherits,
deprecate,
inspect,
format,
debuglog,
isDeepStrictEqual,
types,
TextEncoder: globalThis.TextEncoder,
TextDecoder: globalThis.TextDecoder,
};

View 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");