@gjsify/v8 0.21.0 → 0.23.0
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/README.md +54 -1
- package/lib/esm/heap/darwin.js +1 -0
- package/lib/esm/heap/index.js +1 -0
- package/lib/esm/heap/linux.js +2 -0
- package/lib/esm/heap/types.js +0 -0
- package/lib/esm/heap/win32.js +1 -0
- package/lib/esm/index.js +1 -1
- package/lib/types/heap/darwin.d.ts +14 -0
- package/lib/types/heap/index.d.ts +43 -0
- package/lib/types/heap/linux.d.ts +10 -0
- package/lib/types/heap/types.d.ts +15 -0
- package/lib/types/heap/win32.d.ts +2 -0
- package/lib/types/index.d.ts +1 -1
- package/package.json +6 -3
- package/lib/esm/heap.js +0 -2
- package/lib/types/heap.d.ts +0 -16
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @gjsify/v8
|
|
2
2
|
|
|
3
|
-
GJS
|
|
3
|
+
GJS implementation of the Node.js `v8` module. Provides V8-wire-format
|
|
4
|
+
`serialize`/`deserialize` (`Serializer`, `Deserializer`, `DefaultSerializer`,
|
|
5
|
+
`DefaultDeserializer`) plus `getHeapStatistics()`.
|
|
4
6
|
|
|
5
7
|
Part of the [gjsify](https://github.com/gjsify/gjsify) project — Node.js and Web APIs for GJS (GNOME JavaScript).
|
|
6
8
|
|
|
@@ -25,6 +27,57 @@ const buf = serialize({ hello: 'world' });
|
|
|
25
27
|
const obj = deserialize(buf);
|
|
26
28
|
```
|
|
27
29
|
|
|
30
|
+
## `getHeapStatistics()` — what the numbers mean
|
|
31
|
+
|
|
32
|
+
Node's `v8.getHeapStatistics()` reports V8's own accounting of its heap.
|
|
33
|
+
GJS runs on SpiderMonkey, which exposes no equivalent surface (there is nothing
|
|
34
|
+
like `HeapStatistics` on `imports.system`), so the memory-derived fields are
|
|
35
|
+
approximated from the **operating system's view of the whole process** instead
|
|
36
|
+
of the JS heap alone. Fields V8 computes from engine internals we cannot reach
|
|
37
|
+
are reported as `0`.
|
|
38
|
+
|
|
39
|
+
The result always has all 14 Node fields, always numeric — this function never
|
|
40
|
+
throws, on any platform.
|
|
41
|
+
|
|
42
|
+
| Field | Value on GJS |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `total_heap_size` | process virtual size |
|
|
45
|
+
| `total_physical_size` | process resident set size |
|
|
46
|
+
| `used_heap_size` | process resident set size |
|
|
47
|
+
| `malloced_memory` | process data-segment size (Linux only) |
|
|
48
|
+
| `peak_malloced_memory` | peak process virtual size (Linux only) |
|
|
49
|
+
| `total_heap_size_executable`, `total_available_size`, `heap_size_limit`, `does_zap_garbage`, `number_of_native_contexts`, `number_of_detached_contexts`, `total_global_handles_size`, `used_global_handles_size`, `external_memory` | `0` — no SpiderMonkey equivalent |
|
|
50
|
+
|
|
51
|
+
### Platform support
|
|
52
|
+
|
|
53
|
+
The reader lives in `src/heap/` (`linux.ts` / `darwin.ts` / `win32.ts` behind an
|
|
54
|
+
`index.ts`, mirroring `@gjsify/os`). Detection is capability-based — the
|
|
55
|
+
filesystem is probed for what is actually there, not a `uname` string parsed.
|
|
56
|
+
|
|
57
|
+
| Platform | Source | Coverage |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| Linux (incl. Android, Flatpak, containers) | `/proc/self/status` — one `g_file_get_contents()`, no subprocess | `VmSize`, `VmRSS`, `VmData`, `VmPeak` |
|
|
60
|
+
| macOS | `ps -o rss=,vsz=` — no procfs; Mach's `task_info()` (what libuv uses) needs a native bridge | `rss`, `vsz` only; `malloced_memory` and `peak_malloced_memory` stay `0` |
|
|
61
|
+
| Windows | none reachable | all memory fields `0` — see below |
|
|
62
|
+
| any other POSIX | none reachable | all memory fields `0` |
|
|
63
|
+
|
|
64
|
+
**Degraded contract on Windows.** There is no `/proc` and no `ps(1)`. The native
|
|
65
|
+
source is `GetProcessMemoryInfo()` (psapi), which GLib does not wrap and GJS
|
|
66
|
+
cannot call without a native bridge; shelling out to `wmic` / `tasklist` /
|
|
67
|
+
PowerShell would cost hundreds of milliseconds per call and `wmic` is deprecated
|
|
68
|
+
and removed from recent Windows builds. `getHeapStatistics()` therefore returns
|
|
69
|
+
the **all-zero** shape: every field present and numeric so destructuring callers
|
|
70
|
+
keep working, none of them meaningful. This is byte-for-byte the same value the
|
|
71
|
+
Linux reader already produced when `/proc` was unreadable, so no consumer sees a
|
|
72
|
+
new shape. Callers that need a real number should check for `0`.
|
|
73
|
+
|
|
74
|
+
### Not implemented
|
|
75
|
+
|
|
76
|
+
`getHeapSpaceStatistics()` returns `[]`, `getHeapCodeStatistics()` returns
|
|
77
|
+
zeros, and `writeHeapSnapshot()` / `setFlagsFromString()` / the profiler and
|
|
78
|
+
`promiseHooks` surfaces are stubs — all of them are V8-internal APIs with no
|
|
79
|
+
SpiderMonkey counterpart.
|
|
80
|
+
|
|
28
81
|
## License
|
|
29
82
|
|
|
30
83
|
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import e from"@girs/glib-2.0";function readProcessMemory(){try{let[t,n]=e.spawn_command_line_sync(`sh -c 'ps -o rss=,vsz= -p $PPID'`);if(!t||!n)return null;let r=new TextDecoder().decode(n).trim(),i=/^(\d+)\s+(\d+)$/.exec(r);return i?{virtual:parseInt(i[2],10)*1024,resident:parseInt(i[1],10)*1024,data:0,peak:0}:null}catch{return null}}export{readProcessMemory};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{readProcessMemory as e}from"./darwin.js";import{readProcessMemory as t}from"./linux.js";import{readProcessMemory as n}from"./win32.js";import r from"@girs/glib-2.0";let i=null;function detectHeapPlatform(){return i===null&&(i=r.get_current_dir().startsWith(`/`)?r.file_test(`/proc/self/status`,r.FileTest.EXISTS)?`linux`:r.file_test(`/System/Library/CoreServices/SystemVersion.plist`,r.FileTest.EXISTS)?`darwin`:`unknown`:`win32`),i}const a={virtual:0,resident:0,data:0,peak:0};function readProcessMemory(){switch(detectHeapPlatform()){case`linux`:return t();case`darwin`:return e();case`win32`:return n();default:return null}}function getHeapStatistics(){let e=readProcessMemory()??a;return{total_heap_size:e.virtual,total_heap_size_executable:0,total_physical_size:e.resident,total_available_size:0,used_heap_size:e.resident,heap_size_limit:0,malloced_memory:e.data,peak_malloced_memory:e.peak,does_zap_garbage:0,number_of_native_contexts:0,number_of_detached_contexts:0,total_global_handles_size:0,used_global_handles_size:0,external_memory:0}}export{detectHeapPlatform,getHeapStatistics,readProcessMemory};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import e from"@girs/glib-2.0";function readProcessMemory(){let t;try{let[n,r]=e.file_get_contents(`/proc/self/status`);if(!n||!r)return null;t=new TextDecoder().decode(r)}catch{return null}let n=new Map;for(let e of t.split(`
|
|
2
|
+
`)){let t=/^(\w+):\s+(\d+)(\s+kB)?/.exec(e);t&&n.set(t[1],parseInt(t[2])*(t[3]?1024:1))}return n.size===0?null:{virtual:n.get(`VmSize`)??0,resident:n.get(`VmRSS`)??0,data:n.get(`VmData`)??0,peak:n.get(`VmPeak`)??0}}export{readProcessMemory};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";function readProcessMemory(){return null}export{readProcessMemory};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{getHeapStatistics as e}from"./heap.js";import{DefaultDeserializer as t,DefaultSerializer as n,Deserializer as r,Serializer as i}from"./serdes.js";function serialize(e){let t=new n;return t.writeHeader(),t.writeValue(e),t.releaseBuffer()}function deserialize(e){let n=new t(e);return n.readHeader(),n.readValue()}function getHeapSpaceStatistics(){return[]}function getHeapCodeStatistics(){return{code_and_metadata_size:0,bytecode_and_metadata_size:0,external_script_source_size:0,cpu_profiler_metadata_size:0}}function setFlagsFromString(e){}function getHeapSnapshot(e){return null}function writeHeapSnapshot(e){return``}function isStringOneByteRepresentation(e){for(let t=0;t<e.length;t++)if(e.charCodeAt(t)>255)return!1;return!0}var GCProfiler=class{#e=!1;#t=0;start(){this.#e||(this.#e=!0,this.#t=Date.now())}stop(){if(this.#e){this.#e=!1;try{let e=globalThis.imports?.system;typeof e?.gc==`function`&&e.gc()}catch{}return{version:1,startTime:this.#t,endTime:Date.now(),stats:[]}}}[Symbol.dispose](){this.stop()}},SyncCPUProfileHandle=class{stop(){}[Symbol.dispose](){this.stop()}};function startCpuProfile(){return new SyncCPUProfileHandle}var a={getHeapStatistics:e,getHeapSpaceStatistics,getHeapCodeStatistics,setFlagsFromString,getHeapSnapshot,writeHeapSnapshot,serialize,deserialize,isStringOneByteRepresentation,Serializer:i,Deserializer:r,DefaultSerializer:n,DefaultDeserializer:t,GCProfiler,startCpuProfile};export{t as DefaultDeserializer,n as DefaultSerializer,r as Deserializer,GCProfiler,i as Serializer,SyncCPUProfileHandle,a as default,deserialize,getHeapCodeStatistics,getHeapSnapshot,getHeapSpaceStatistics,e as getHeapStatistics,isStringOneByteRepresentation,serialize,setFlagsFromString,startCpuProfile,writeHeapSnapshot};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{getHeapStatistics as e}from"./heap/index.js";import{DefaultDeserializer as t,DefaultSerializer as n,Deserializer as r,Serializer as i}from"./serdes.js";function serialize(e){let t=new n;return t.writeHeader(),t.writeValue(e),t.releaseBuffer()}function deserialize(e){let n=new t(e);return n.readHeader(),n.readValue()}function getHeapSpaceStatistics(){return[]}function getHeapCodeStatistics(){return{code_and_metadata_size:0,bytecode_and_metadata_size:0,external_script_source_size:0,cpu_profiler_metadata_size:0}}function setFlagsFromString(e){}function getHeapSnapshot(e){return null}function writeHeapSnapshot(e){return``}function isStringOneByteRepresentation(e){for(let t=0;t<e.length;t++)if(e.charCodeAt(t)>255)return!1;return!0}var GCProfiler=class{#e=!1;#t=0;start(){this.#e||(this.#e=!0,this.#t=Date.now())}stop(){if(this.#e){this.#e=!1;try{let e=globalThis.imports?.system;typeof e?.gc==`function`&&e.gc()}catch{}return{version:1,startTime:this.#t,endTime:Date.now(),stats:[]}}}[Symbol.dispose](){this.stop()}},SyncCPUProfileHandle=class{stop(){}[Symbol.dispose](){this.stop()}};function startCpuProfile(){return new SyncCPUProfileHandle}var a={getHeapStatistics:e,getHeapSpaceStatistics,getHeapCodeStatistics,setFlagsFromString,getHeapSnapshot,writeHeapSnapshot,serialize,deserialize,isStringOneByteRepresentation,Serializer:i,Deserializer:r,DefaultSerializer:n,DefaultDeserializer:t,GCProfiler,startCpuProfile};export{t as DefaultDeserializer,n as DefaultSerializer,r as Deserializer,GCProfiler,i as Serializer,SyncCPUProfileHandle,a as default,deserialize,getHeapCodeStatistics,getHeapSnapshot,getHeapSpaceStatistics,e as getHeapStatistics,isStringOneByteRepresentation,serialize,setFlagsFromString,startCpuProfile,writeHeapSnapshot};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ProcessMemory } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read this process's `rss` / `vsz` via `ps`.
|
|
4
|
+
*
|
|
5
|
+
* The pid is obtained without any extra binding by asking a short-lived shell
|
|
6
|
+
* for its OWN parent — `g_spawn_command_line_sync()` forks us, so the shell's
|
|
7
|
+
* `$PPID` is this process. Both `ps` columns are in KiB on macOS; `-o rss=`
|
|
8
|
+
* suppresses the header so the output is a bare `<rss> <vsz>` line.
|
|
9
|
+
*
|
|
10
|
+
* Spawning for a memory reading is heavier than Linux's single file read, but
|
|
11
|
+
* `getHeapStatistics()` is a diagnostics call, not a hot path. Returns `null`
|
|
12
|
+
* on any failure so the caller falls back to the all-zero contract.
|
|
13
|
+
*/
|
|
14
|
+
export declare function readProcessMemory(): ProcessMemory | null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ProcessMemory } from './types.js';
|
|
2
|
+
export type { ProcessMemory };
|
|
3
|
+
export type HeapPlatform = 'linux' | 'darwin' | 'win32' | 'unknown';
|
|
4
|
+
/**
|
|
5
|
+
* Detect which reader applies, once per process:
|
|
6
|
+
*
|
|
7
|
+
* - Windows — GLib returns native paths, so `g_get_current_dir()` is
|
|
8
|
+
* drive-rooted (`C:\…`) instead of `/`-rooted.
|
|
9
|
+
* - Linux — `/proc/self/status` exists (procfs is Linux-only).
|
|
10
|
+
* - macOS — no procfs, but the system version plist is always present.
|
|
11
|
+
* - anything else — no reader; the all-zero contract applies.
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectHeapPlatform(): HeapPlatform;
|
|
14
|
+
/** Read the current process's memory figures, or `null` if unavailable here. */
|
|
15
|
+
export declare function readProcessMemory(): ProcessMemory | null;
|
|
16
|
+
export interface HeapStatistics {
|
|
17
|
+
total_heap_size: number;
|
|
18
|
+
total_heap_size_executable: number;
|
|
19
|
+
total_physical_size: number;
|
|
20
|
+
total_available_size: number;
|
|
21
|
+
used_heap_size: number;
|
|
22
|
+
heap_size_limit: number;
|
|
23
|
+
malloced_memory: number;
|
|
24
|
+
peak_malloced_memory: number;
|
|
25
|
+
does_zap_garbage: number;
|
|
26
|
+
number_of_native_contexts: number;
|
|
27
|
+
number_of_detached_contexts: number;
|
|
28
|
+
total_global_handles_size: number;
|
|
29
|
+
used_global_handles_size: number;
|
|
30
|
+
external_memory: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Node-shaped `v8.getHeapStatistics()`.
|
|
34
|
+
*
|
|
35
|
+
* Every field is always present and numeric — Node never throws here and
|
|
36
|
+
* neither do we. Fields V8 computes from engine internals we have no access to
|
|
37
|
+
* (`heap_size_limit`, `does_zap_garbage`, the context/handle counters, …) are
|
|
38
|
+
* reported as `0`; the memory-derived fields come from the platform reader
|
|
39
|
+
* above and are `0` too when no reader is available (Windows, or a Linux host
|
|
40
|
+
* with `/proc` masked). Callers that destructure the result keep working
|
|
41
|
+
* everywhere; callers that need a meaningful number should check for `0`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function getHeapStatistics(): HeapStatistics;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProcessMemory } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read `VmSize` / `VmRSS` / `VmData` / `VmPeak` out of `/proc/self/status`.
|
|
4
|
+
*
|
|
5
|
+
* procfs is Linux-only but is present on every mainstream distribution and
|
|
6
|
+
* inside Flatpak/OCI containers, so this is the fast path (a single
|
|
7
|
+
* `g_file_get_contents()`, no subprocess). Returns `null` when procfs is not
|
|
8
|
+
* readable so the caller can fall back to the documented all-zero contract.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readProcessMemory(): ProcessMemory | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process memory figures, in BYTES. A reader sets `0` for any figure the
|
|
3
|
+
* platform does not expose (rather than guessing), and returns `null` from
|
|
4
|
+
* `readProcessMemory()` when it can read nothing at all.
|
|
5
|
+
*/
|
|
6
|
+
export interface ProcessMemory {
|
|
7
|
+
/** Virtual memory size (Linux `VmSize`, BSD `vsz`). */
|
|
8
|
+
virtual: number;
|
|
9
|
+
/** Resident set size (Linux `VmRSS`, BSD `rss`). */
|
|
10
|
+
resident: number;
|
|
11
|
+
/** Data-segment size (Linux `VmData`). */
|
|
12
|
+
data: number;
|
|
13
|
+
/** Peak virtual memory size (Linux `VmPeak`). */
|
|
14
|
+
peak: number;
|
|
15
|
+
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getHeapStatistics } from './heap.js';
|
|
1
|
+
import { getHeapStatistics } from './heap/index.js';
|
|
2
2
|
import { Serializer, Deserializer, DefaultSerializer, DefaultDeserializer } from './serdes.js';
|
|
3
3
|
export { getHeapStatistics };
|
|
4
4
|
export { Serializer, Deserializer, DefaultSerializer, DefaultDeserializer };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/v8",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Node.js v8 module for Gjs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -33,11 +33,14 @@
|
|
|
33
33
|
"v8"
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@gjsify/cli": "^0.
|
|
37
|
-
"@gjsify/unit": "^0.
|
|
36
|
+
"@gjsify/cli": "^0.23.0",
|
|
37
|
+
"@gjsify/unit": "^0.23.0",
|
|
38
38
|
"@types/node": "^25.9.2",
|
|
39
39
|
"typescript": "^6.0.3"
|
|
40
40
|
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@girs/glib-2.0": "^4.1.0"
|
|
43
|
+
},
|
|
41
44
|
"gjsify": {
|
|
42
45
|
"runtimes": {
|
|
43
46
|
"gjs": "polyfill",
|
package/lib/esm/heap.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import e from"@girs/glib-2.0";function readProcStatus(){let t=new Map;try{let[n,r]=e.file_get_contents(`/proc/self/status`);if(!n||!r)return t;let i=new TextDecoder().decode(r);for(let e of i.split(`
|
|
2
|
-
`)){let n=/^(\w+):\s+(\d+)(\s+kB)?/.exec(e);n&&t.set(n[1],parseInt(n[2])*(n[3]?1024:1))}}catch{}return t}function getHeapStatistics(){let e=readProcStatus();return{total_heap_size:e.get(`VmSize`)??0,total_heap_size_executable:0,total_physical_size:e.get(`VmRSS`)??0,total_available_size:0,used_heap_size:e.get(`VmRSS`)??0,heap_size_limit:0,malloced_memory:e.get(`VmData`)??0,peak_malloced_memory:e.get(`VmPeak`)??0,does_zap_garbage:0,number_of_native_contexts:0,number_of_detached_contexts:0,total_global_handles_size:0,used_global_handles_size:0,external_memory:0}}export{getHeapStatistics};
|
package/lib/types/heap.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare function getHeapStatistics(): {
|
|
2
|
-
total_heap_size: number;
|
|
3
|
-
total_heap_size_executable: number;
|
|
4
|
-
total_physical_size: number;
|
|
5
|
-
total_available_size: number;
|
|
6
|
-
used_heap_size: number;
|
|
7
|
-
heap_size_limit: number;
|
|
8
|
-
malloced_memory: number;
|
|
9
|
-
peak_malloced_memory: number;
|
|
10
|
-
does_zap_garbage: number;
|
|
11
|
-
number_of_native_contexts: number;
|
|
12
|
-
number_of_detached_contexts: number;
|
|
13
|
-
total_global_handles_size: number;
|
|
14
|
-
used_global_handles_size: number;
|
|
15
|
-
external_memory: number;
|
|
16
|
-
};
|