@gjsify/utils 0.3.13 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/base64.js +63 -61
- package/lib/esm/byte-array.js +10 -4
- package/lib/esm/callable.js +23 -13
- package/lib/esm/cli.js +8 -6
- package/lib/esm/defer.js +9 -4
- package/lib/esm/encoding.js +40 -31
- package/lib/esm/error.js +30 -19
- package/lib/esm/file.js +11 -9
- package/lib/esm/fs.js +18 -16
- package/lib/esm/gio-errors.js +106 -125
- package/lib/esm/gio.js +44 -31
- package/lib/esm/globals.js +11 -6
- package/lib/esm/index.js +20 -18
- package/lib/esm/main-loop.js +40 -22
- package/lib/esm/message.js +9 -9
- package/lib/esm/microtask.js +5 -4
- package/lib/esm/next-tick.js +53 -48
- package/lib/esm/path.js +34 -36
- package/lib/esm/structured-clone.js +187 -157
- package/package.json +6 -6
- package/src/structured-clone.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/lib/esm/base64.js
CHANGED
|
@@ -1,72 +1,74 @@
|
|
|
1
|
+
//#region src/base64.ts
|
|
1
2
|
const B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
2
3
|
const B64_LOOKUP = new Uint8Array(256);
|
|
3
4
|
for (let i = 0; i < B64_CHARS.length; i++) B64_LOOKUP[B64_CHARS.charCodeAt(i)] = i;
|
|
5
|
+
/** Decode a base64 string to a binary string. Uses native atob when available. */
|
|
4
6
|
function atobPolyfill(str) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
if (typeof globalThis.atob === "function") return globalThis.atob(str);
|
|
8
|
+
const cleaned = str.replace(/[=\s]/g, "");
|
|
9
|
+
let result = "";
|
|
10
|
+
let bits = 0;
|
|
11
|
+
let collected = 0;
|
|
12
|
+
for (let i = 0; i < cleaned.length; i++) {
|
|
13
|
+
bits = bits << 6 | B64_LOOKUP[cleaned.charCodeAt(i)];
|
|
14
|
+
collected += 6;
|
|
15
|
+
if (collected >= 8) {
|
|
16
|
+
collected -= 8;
|
|
17
|
+
result += String.fromCharCode(bits >> collected & 255);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
19
21
|
}
|
|
22
|
+
/** Encode a binary string to base64. Uses native btoa when available. */
|
|
20
23
|
function btoaPolyfill(str) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
if (typeof globalThis.btoa === "function") return globalThis.btoa(str);
|
|
25
|
+
let result = "";
|
|
26
|
+
let i = 0;
|
|
27
|
+
for (; i + 2 < str.length; i += 3) {
|
|
28
|
+
const n = str.charCodeAt(i) << 16 | str.charCodeAt(i + 1) << 8 | str.charCodeAt(i + 2);
|
|
29
|
+
result += B64_CHARS[n >> 18 & 63] + B64_CHARS[n >> 12 & 63] + B64_CHARS[n >> 6 & 63] + B64_CHARS[n & 63];
|
|
30
|
+
}
|
|
31
|
+
if (i + 1 === str.length) {
|
|
32
|
+
const n = str.charCodeAt(i) << 16;
|
|
33
|
+
result += B64_CHARS[n >> 18 & 63] + B64_CHARS[n >> 12 & 63] + "==";
|
|
34
|
+
} else if (i + 2 === str.length) {
|
|
35
|
+
const n = str.charCodeAt(i) << 16 | str.charCodeAt(i + 1) << 8;
|
|
36
|
+
result += B64_CHARS[n >> 18 & 63] + B64_CHARS[n >> 12 & 63] + B64_CHARS[n >> 6 & 63] + "=";
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
36
39
|
}
|
|
40
|
+
/** Decode a base64 string directly to Uint8Array (avoids lossy atob string round-trip). */
|
|
37
41
|
function base64Decode(str) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
const cleaned = str.replace(/[=\s]/g, "");
|
|
43
|
+
const bytes = new Uint8Array(cleaned.length * 3 >> 2);
|
|
44
|
+
let bits = 0;
|
|
45
|
+
let collected = 0;
|
|
46
|
+
let pos = 0;
|
|
47
|
+
for (let i = 0; i < cleaned.length; i++) {
|
|
48
|
+
bits = bits << 6 | B64_LOOKUP[cleaned.charCodeAt(i)];
|
|
49
|
+
collected += 6;
|
|
50
|
+
if (collected >= 8) {
|
|
51
|
+
collected -= 8;
|
|
52
|
+
bytes[pos++] = bits >> collected & 255;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return bytes.subarray(0, pos);
|
|
52
56
|
}
|
|
57
|
+
/** Encode a Uint8Array to base64 string. */
|
|
53
58
|
function base64Encode(bytes) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
let result = "";
|
|
60
|
+
const len = bytes.length;
|
|
61
|
+
for (let i = 0; i < len; i += 3) {
|
|
62
|
+
const b0 = bytes[i];
|
|
63
|
+
const b1 = i + 1 < len ? bytes[i + 1] : 0;
|
|
64
|
+
const b2 = i + 2 < len ? bytes[i + 2] : 0;
|
|
65
|
+
result += B64_CHARS[b0 >> 2];
|
|
66
|
+
result += B64_CHARS[(b0 & 3) << 4 | b1 >> 4];
|
|
67
|
+
result += i + 1 < len ? B64_CHARS[(b1 & 15) << 2 | b2 >> 6] : "=";
|
|
68
|
+
result += i + 2 < len ? B64_CHARS[b2 & 63] : "=";
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
66
71
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
base64Encode,
|
|
71
|
-
btoaPolyfill
|
|
72
|
-
};
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
export { atobPolyfill, base64Decode, base64Encode, btoaPolyfill };
|
package/lib/esm/byte-array.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
//#region src/byte-array.ts
|
|
2
|
+
/**
|
|
3
|
+
* Convert GLib.Bytes to Uint8Array using GJS's byteArray module.
|
|
4
|
+
* This wraps the GJS-specific `imports.byteArray.fromGBytes()` API
|
|
5
|
+
* with proper typing to eliminate `as any` casts throughout the codebase.
|
|
6
|
+
*/
|
|
1
7
|
function gbytesToUint8Array(bytes) {
|
|
2
|
-
|
|
8
|
+
return imports.byteArray.fromGBytes(bytes);
|
|
3
9
|
}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { gbytesToUint8Array };
|
package/lib/esm/callable.js
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
//#region src/callable.ts
|
|
2
|
+
/**
|
|
3
|
+
* Wrap an ES6 class so it supports both the modern `new Cls(...)` pattern and
|
|
4
|
+
* the legacy `Cls.call(thisArg, ...)` pattern.
|
|
5
|
+
*
|
|
6
|
+
* The `apply` trap materialises a temporary instance via `Reflect.construct`
|
|
7
|
+
* (so field initializers and constructor bodies run normally), then transplants
|
|
8
|
+
* its own property descriptors onto `thisArg`. The default Proxy traps pass
|
|
9
|
+
* `construct`, `get` and `getPrototypeOf` straight through, so `new Wrapped()`,
|
|
10
|
+
* `Wrapped.prototype` (consulted by `util.inherits`) and `instance instanceof
|
|
11
|
+
* Wrapped` all behave identically to the underlying class.
|
|
12
|
+
*/
|
|
1
13
|
function makeCallable(Cls) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
});
|
|
14
|
+
return new Proxy(Cls, { apply(target, thisArg, args) {
|
|
15
|
+
const tmp = Reflect.construct(target, args, target);
|
|
16
|
+
for (const key of Reflect.ownKeys(tmp)) {
|
|
17
|
+
const desc = Object.getOwnPropertyDescriptor(tmp, key);
|
|
18
|
+
if (desc) Object.defineProperty(thisArg, key, desc);
|
|
19
|
+
}
|
|
20
|
+
return thisArg;
|
|
21
|
+
} });
|
|
12
22
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { makeCallable };
|
package/lib/esm/cli.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import GLib from "@girs/glib-2.0";
|
|
2
|
+
|
|
3
|
+
//#region src/cli.ts
|
|
2
4
|
const byteArray = imports.byteArray;
|
|
3
5
|
const cli = (commandLine) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
export {
|
|
9
|
-
cli
|
|
6
|
+
const [res, out, err, status] = GLib.spawn_command_line_sync(commandLine);
|
|
7
|
+
if (err.byteLength) throw new Error(byteArray.toString(err));
|
|
8
|
+
return byteArray.toString(out);
|
|
10
9
|
};
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { cli };
|
package/lib/esm/defer.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
//#region src/defer.ts
|
|
2
|
+
/**
|
|
3
|
+
* Defer an event emission to the next macrotask, matching Node.js behavior
|
|
4
|
+
* for server 'listening', 'close', and 'error' events.
|
|
5
|
+
*/
|
|
1
6
|
function deferEmit(emitter, event, ...args) {
|
|
2
|
-
|
|
7
|
+
setTimeout(() => emitter.emit(event, ...args), 0);
|
|
3
8
|
}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { deferEmit };
|
package/lib/esm/encoding.js
CHANGED
|
@@ -1,35 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/encoding.ts
|
|
2
|
+
const VALID_ENCODINGS = [
|
|
3
|
+
"utf8",
|
|
4
|
+
"ascii",
|
|
5
|
+
"latin1",
|
|
6
|
+
"binary",
|
|
7
|
+
"base64",
|
|
8
|
+
"base64url",
|
|
9
|
+
"hex",
|
|
10
|
+
"ucs2",
|
|
11
|
+
"utf16le"
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Normalize an encoding string to a canonical encoding value.
|
|
15
|
+
* Returns 'utf8' as default for undefined/null/empty input.
|
|
16
|
+
*/
|
|
2
17
|
function normalizeEncoding(enc) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
case "hex":
|
|
18
|
-
return "hex";
|
|
19
|
-
case "ucs2":
|
|
20
|
-
case "utf16le":
|
|
21
|
-
return "utf16le";
|
|
22
|
-
default:
|
|
23
|
-
return "utf8";
|
|
24
|
-
}
|
|
18
|
+
if (!enc || enc === "utf8" || enc === "utf-8") return "utf8";
|
|
19
|
+
const lower = ("" + enc).toLowerCase().replace(/-/g, "");
|
|
20
|
+
switch (lower) {
|
|
21
|
+
case "utf8": return "utf8";
|
|
22
|
+
case "ascii": return "ascii";
|
|
23
|
+
case "latin1":
|
|
24
|
+
case "binary": return "latin1";
|
|
25
|
+
case "base64": return "base64";
|
|
26
|
+
case "base64url": return "base64url";
|
|
27
|
+
case "hex": return "hex";
|
|
28
|
+
case "ucs2":
|
|
29
|
+
case "utf16le": return "utf16le";
|
|
30
|
+
default: return "utf8";
|
|
31
|
+
}
|
|
25
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Check that an encoding string is valid. Throws TypeError if not.
|
|
35
|
+
*/
|
|
26
36
|
function checkEncoding(encoding) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
const lower = ("" + encoding).toLowerCase().replace(/-/g, "");
|
|
38
|
+
if (!VALID_ENCODINGS.includes(lower)) {
|
|
39
|
+
throw new TypeError(`Unknown encoding: ${encoding}`);
|
|
40
|
+
}
|
|
31
41
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { checkEncoding, normalizeEncoding };
|
package/lib/esm/error.js
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
|
+
//#region src/error.ts
|
|
2
|
+
/**
|
|
3
|
+
* Defines the static Error.captureStackTrace method,
|
|
4
|
+
* this is not present in SpiderMonkey because it comes from V8
|
|
5
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#static_methods
|
|
6
|
+
* @see https://nodejs.org/dist/latest-v18.x/docs/api/errors.html#errorcapturestacktracetargetobject-constructoropt
|
|
7
|
+
*/
|
|
1
8
|
const initErrorV8Methods = (ErrorConstructor) => {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
if (!Error.captureStackTrace) {
|
|
10
|
+
/**
|
|
11
|
+
* A non-standard V8 function.
|
|
12
|
+
* Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.
|
|
13
|
+
* @param targetObject
|
|
14
|
+
* @param constructorOpt
|
|
15
|
+
*/
|
|
16
|
+
Error.captureStackTrace = function(targetObject, constructorOpt) {
|
|
17
|
+
const container = new Error();
|
|
18
|
+
const target = constructorOpt || targetObject;
|
|
19
|
+
Object.defineProperty(target, "stack", {
|
|
20
|
+
configurable: true,
|
|
21
|
+
get: function getStack() {
|
|
22
|
+
var stack = container.stack;
|
|
23
|
+
Object.defineProperty(this, "stack", { value: stack });
|
|
24
|
+
return stack;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
}
|
|
21
29
|
};
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { initErrorV8Methods };
|
package/lib/esm/file.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import GLib from "@girs/glib-2.0";
|
|
2
|
+
|
|
3
|
+
//#region src/file.ts
|
|
2
4
|
const byteArray = imports.byteArray;
|
|
3
5
|
const readJSON = (path) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
export {
|
|
12
|
-
readJSON
|
|
6
|
+
const [ok, contents] = GLib.file_get_contents(path);
|
|
7
|
+
if (ok) {
|
|
8
|
+
const map = JSON.parse(byteArray.toString(contents));
|
|
9
|
+
return map;
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Error on require "${path}"`);
|
|
13
12
|
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { readJSON };
|
package/lib/esm/fs.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import Gio from "@girs/gio-2.0";
|
|
2
2
|
import GioUnix from "@girs/giounix-2.0";
|
|
3
|
+
|
|
4
|
+
//#region src/fs.ts
|
|
5
|
+
/** Check if a file descriptor exists */
|
|
3
6
|
const existsFD = (fd) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
try {
|
|
8
|
+
let stream = GioUnix.InputStream.new(fd, false);
|
|
9
|
+
stream.close(null);
|
|
10
|
+
return true;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
11
14
|
};
|
|
12
15
|
function existsSync(path) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if (typeof path !== "string" || path === "") {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const file = Gio.File.new_for_path(path);
|
|
20
|
+
return file.query_exists(null);
|
|
18
21
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { existsFD, existsSync };
|