bun-memory 1.0.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/LICENSE +21 -0
- package/README.md +72 -0
- package/index.ts +3 -0
- package/package.json +47 -0
- package/structs/Memory.ts +1301 -0
- package/structs/Win32Error.ts +113 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Win32 error helper for Bun using `bun:ffi`.
|
|
3
|
+
*
|
|
4
|
+
* Exposes {@link Win32Error}, an `Error` subclass that formats Windows error codes
|
|
5
|
+
* using `FormatMessageW` from `kernel32.dll`. Messages are memoized for performance
|
|
6
|
+
* and the resulting error string contains the failing operation, the numeric code,
|
|
7
|
+
* and the human-readable description.
|
|
8
|
+
*
|
|
9
|
+
* For a complete list of error codes, visit…
|
|
10
|
+
* https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* - Requires Windows.
|
|
14
|
+
* - Requires Bun runtime (uses `bun:ffi`).
|
|
15
|
+
* - Designed to be fast and allocation‑conscious.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { dlopen, FFIType } from 'bun:ffi';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Minimal Kernel32 FFI surface used by this module.
|
|
22
|
+
* Currently binds only `FormatMessageW`.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const { symbols: Kernel32 } = dlopen('kernel32.dll', {
|
|
26
|
+
FormatMessageW: { args: [FFIType.u32, FFIType.u64, FFIType.u32, FFIType.u32, FFIType.ptr, FFIType.u32, FFIType.u64], returns: FFIType.u32 },
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Error type representing a Windows (Win32) system error.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const hSnapshot = Kernel32.CreateToolhelp32Snapshot(dwFlags, th32ProcessID);
|
|
35
|
+
*
|
|
36
|
+
* if(hSnapshot === -1) {
|
|
37
|
+
* // Wrap with context and the last error code you observed
|
|
38
|
+
* throw new Win32Error('CreateToolhelp32Snapshot', Kernel32.GetLastError());
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
class Win32Error extends Error {
|
|
44
|
+
/**
|
|
45
|
+
* Create a formatted Win32 error.
|
|
46
|
+
*
|
|
47
|
+
* @param what Name of the operation that failed (e.g., `"OpenProcess"`).
|
|
48
|
+
* @param code The Win32 error code (DWORD) associated with the failure.
|
|
49
|
+
* @remarks
|
|
50
|
+
* The constructor formats the error message using `FormatMessageW` and memoizes
|
|
51
|
+
* the message text per code to avoid repeated system calls.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
constructor(what: string, code: number) {
|
|
55
|
+
let message = Win32Error.formatMessageWCache.get(code);
|
|
56
|
+
|
|
57
|
+
if (message === undefined) {
|
|
58
|
+
const dwFlags = 0x00001000 /* FORMAT_MESSAGE_FROM_SYSTEM */ | 0x00000200; /* FORMAT_MESSAGE_IGNORE_INSERTS */
|
|
59
|
+
const dwMessageId = code >>> 0;
|
|
60
|
+
const lpBuffer = Win32Error.scratch4096;
|
|
61
|
+
const nSize = lpBuffer.byteLength / 2;
|
|
62
|
+
|
|
63
|
+
const tChars = Kernel32.FormatMessageW(dwFlags, 0n, dwMessageId, 0, lpBuffer, nSize, 0n);
|
|
64
|
+
|
|
65
|
+
message =
|
|
66
|
+
tChars !== 0
|
|
67
|
+
? lpBuffer
|
|
68
|
+
.toString('utf16le', 0, tChars * 2)
|
|
69
|
+
.replaceAll(/(\r?\n)+/g, ' ')
|
|
70
|
+
.trim()
|
|
71
|
+
: 'Unknown error';
|
|
72
|
+
|
|
73
|
+
Win32Error.formatMessageWCache.set(code, message);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
super(`${what} failed (${code}): ${message}`);
|
|
77
|
+
|
|
78
|
+
this.code = code;
|
|
79
|
+
this.name = 'Win32Error';
|
|
80
|
+
this.what = what;
|
|
81
|
+
|
|
82
|
+
Error.captureStackTrace?.(this, Win32Error);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Cache of formatted messages keyed by Win32 error code to minimize FFI calls.
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
private static readonly formatMessageWCache = new Map<number, string>();
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Temporary wide‑character buffer used as the target for `FormatMessageW`.
|
|
94
|
+
* Uses 4,096 bytes which is ample for typical system messages.
|
|
95
|
+
* @private
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
private static readonly scratch4096 = Buffer.allocUnsafe(4_096);
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The Win32 error code associated with this failure.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
public readonly code: number;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* The operation or API name that failed.
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
public readonly what: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export default Win32Error;
|