diff options
| author | EuAndreh <eu@euandre.org> | 2025-07-05 06:36:34 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2025-07-07 05:53:44 -0300 |
| commit | d8467dda4ec928b3a10e6ae0212a17e47fba9059 (patch) | |
| tree | 6c1be27535b81126076fbc7a2a691db120db5999 /src/sjs.js | |
| parent | Import existing code as-is (diff) | |
| download | sjs-d8467dda4ec928b3a10e6ae0212a17e47fba9059.tar.gz sjs-d8467dda4ec928b3a10e6ae0212a17e47fba9059.tar.xz | |
Use .mjs extension; add reduce(); finish tests; export names correctly.
Diffstat (limited to 'src/sjs.js')
| -rw-r--r-- | src/sjs.js | 304 |
1 files changed, 0 insertions, 304 deletions
diff --git a/src/sjs.js b/src/sjs.js deleted file mode 100644 index 799f964..0000000 --- a/src/sjs.js +++ /dev/null @@ -1,304 +0,0 @@ -export const getIn = (obj, path) => - path.length === 0 - ? obj - : getIn(obj?.[path[0]], path.slice(1)); - -export const merge = (lhs, rhs) => { - if (lhs === undefined) { - return rhs; - } - - if (rhs === undefined) { - return lfs; - } - - if (typeof lhs !== "object") { - return rhs; - } - - const lkeys = Object.keys(lhs); - const rkeys = Object.keys(rhs); - const allKeys = lkeys.concat(rkeys); - return [...new Set(allKeys)].reduce( - (o, key) => ({ ...o, [key]: merge(lhs[key], rhs[key]) }), - {}, - ); -}; - -export const compareObject = (lhs, rhs) => { - const lstr = Object.entries(lhs).toSorted(); - const rstr = Object.entries(rhs).toSorted(); - - if (lstr < rstr) { - return -1; - } - - if (lstr > rstr) { - return 1; - } - - throw new Error("unreachable"); -}; - -const FROM = /[&<>'"]/g; - -const ESCAPES = { - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' -}; - -const mappingFn = c => ESCAPES[c]; - -export const escape = s => - String.prototype.replace.call(s, FROM, mappingFn); - -export const eq = (a, b) => { - if (a === b) { - return true; - } - - if (a === null || b === null) { - return false; - } - - if (typeof a != "object" || typeof b != "object") { - return false; - } - - if (Array.isArray(a) !== Array.isArray(b)) { - return false; - } - - if (Object.keys(a).length !== Object.keys(b).length) { - return false; - } - - for (const k in a) { - if (!b.hasOwnProperty(k)) { - return false; - } - if (!eq(a[k], b[k])) { - return false; - } - } - return true; -}; - -export const keys = (ks, obj) => - ks.reduce( - (ret, k) => - obj.hasOwnProperty(k) ? {...ret, [k]: obj[k]} : ret, - {}, - ); - -export const difference = (a, b) => { - const diff = new Set(a); - for (const el of b) { - diff.delete(el); - } - return diff; -}; - -export const assocIn = (obj, path, value) => - path.length === 0 ? obj : - path.length === 1 ? { ...obj, [path[0]]: value } : - { - ...obj, - [path[0]]: assocIn( - (obj[path[0]] || {}), - path.slice(1), - value - ) - }; - -export const dissoc = (obj, key) => { - const ret = { ...obj }; - delete ret[key] - return ret; -}; - -export const findFirst = (arr, fn) => { - for (const x of arr) { - const ret = fn(x); - if (ret) { - return ret; - } - } - - return null; -}; - -export const partial = (fn, ...startArgs) => - (...endArgs) => - fn(...startArgs, ...endArgs); - -export const strSortFn = (a, b) => a.localeCompare(b, "POSIX"); - -export const undefinedAsNull = x => x === undefined ? null : x; - -export const first = a => a[0]; -export const rest = a => a.slice(1); -export const butlast = a => a.slice(a, a.length - 1); -export const last = a => a[a.length - 1]; - -export const take = function*(n, gen) { - let i = 0n; - for (const x of gen) { - if (i >= n) { - break; - } - i++; - yield x; - } -}; - -export const range = function*(x, y, step = 1n) { - if (x === undefined) { - let i = 0n; - while (true) { - yield i++; - } - } - const [from, to] = y === undefined ? - [0n, x] : - [x, y]; - const fromn = BigInt(from); - const ton = BigInt(to); - const stepn = BigInt(step); - if (stepn === 0n) { - while (true) { - yield fromn; - } - } - if (step < 0n) { - for (let i = fromn; i > ton; i+= stepn) { - yield i; - } - } else { - for (let i = fromn; i < ton; i += stepn) { - yield i; - } - } -}; - -const t = ({ colors, err, assertEq }) => ({ - assertEq, - tap: x => { - err(`tap: ${x}\n`); - return x; - }, - start: msg => { - err(`${msg}:\n`); - }, - testing: async (msg, fn) => { - err(`${colors.yellow("testing")}: ${msg}... `); - try { - await fn(); - } catch (e) { - err(`${colors.red("ERR")}.\n`); - throw e; - } - err(`${colors.green("OK")}.\n`); - }, -}); - -class UnimplementedError extends Error {} - -export const getJSImpl = () => { - if (typeof scriptArgs !== "undefined") { - return "qjs"; - } - if (typeof Deno !== "undefined") { - return "deno"; - } - if (typeof process !== "undefined") { - return "node"; - } - // FIXME: add browser and bun - return "unknown"; -}; - -export const JSImpl = getJSImpl(); - -const mappings = { - ARGV: { - qjs: () => scriptArgs, - node: () => process.argv.slice(1), - deno: () => Deno.mainModule.substring("file://".length), - unknown: () => { - throw new UnimplementedError(`ARGV["${JSImpl}"]`); - }, - }, - exit: { - qjs: async () => { - const { exit } = await import("std"); - return exit; - }, - node: async () => process.exit, - deno: async () => Deno.exit, - unknown: () => { - throw new UnimplementedError(`exit["${JSImpl}"]`); - }, - }, - tconf: { - qjs: async () => await mappings.testConf.unknown(), - deno: async () => await mappings.testConf.node(), - browser: async () => { - class DOMAssertionError extends Error {} - - const w = s => document.querySelector("#test-report").innerHTML += s; - - const red = s => `<span style="color: red; ">${s}</span>`; - const green = s => `<span style="color: green; ">${s}</span>`; - const yellow = s => `<span style="color: darkgoldenrod;">${s}</span>`; - return { - testStart: msg => w(`${msg}:\n`), - testing: msg => w(`${yellow("testing")}: ${msg}...`), - testOK: () => w(` ${green("OK")}.\n`), - assert: (x, msg = "") => { - if (!x) { - w(` ${red("ERROR")}.\n`); - w("\nSee console for details.\n"); - w("If possible, do report them."); - throw new DOMAssertionError(msg); - } - }, - }; - }, - - node: async () => { - const assert = await import("node:assert/strict"); - const process = await import("node:process"); - - const err = x => process.stderr.write(x); - const red = s => `\x1b[31m${s}\x1b[0m`; - const green = s => `\x1b[32m${s}\x1b[0m`; - const yellow = s => `\x1b[33m${s}\x1b[0m`; - - return { - err, - assertEq: assert.deepEqual, - colors: { - red, - green, - yellow, - }, - }; - }, - unknown: () => { throw new UnimplementedError(`exit["${JSImpl}"]`); }, - }, -}; - -export const exit = await mappings.exit[ JSImpl](); -export const ARGV = await mappings.ARGV[ JSImpl](); -export const tconf = await mappings.tconf[JSImpl](); - -export const runTests = async tests => { - const tFinal = t(tconf); - for (const testFn of tests) { - await testFn(tFinal); - } -}; |
