bun-memory 1.1.19 → 1.1.21

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 CHANGED
@@ -42,19 +42,28 @@ const modules = memory.modules;
42
42
 
43
43
  const client = modules['client.dll'];
44
44
 
45
- console.log(`Base address: 0x${client.base.toString(16)}`);
46
- console.log(`Size: ${client.size} bytes`);
45
+ console.log(`Base: 0x%s — Size: %d bytes…`, client.base.toString(16), client.size);
46
+
47
+ const address = memory.follow(client.base + 0x12345678n, [0x10n, 0x20n, 0x30n]);
47
48
 
48
49
  // Read a 32-bit integer…
49
- const value = memory.i32(client.base + 0x12345678n);
50
+ const value = memory.i32(address);
50
51
 
51
52
  // Write a float…
52
- memory.f32(client.base + 0x12345678n, 3.14159);
53
+ memory.f32(address, 3.14159);
53
54
 
54
55
  // Clean up…
55
56
  memory.close();
56
57
  ```
57
58
 
59
+ ### API — Follow / Read / Write
60
+
61
+ Low-level helpers for pointer resolution and raw, allocation-free memory transfers. Use these when you need maximum control or want to reuse your own scratches.
62
+
63
+ - follow
64
+ - read
65
+ - write
66
+
58
67
  ### API — Typed Reads / Writes
59
68
 
60
69
  A `Memory` instance exposes typed helpers for reading and writing process memory. Pairs indicate
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  "url": "git://github.com/obscuritysrl/bun-memory.git"
23
23
  },
24
24
  "type": "module",
25
- "version": "1.1.19",
25
+ "version": "1.1.21",
26
26
  "main": "./index.ts",
27
27
  "keywords": [
28
28
  "bun",
package/structs/Memory.ts CHANGED
@@ -260,6 +260,63 @@ class Memory {
260
260
 
261
261
  // Core memory operations
262
262
 
263
+ /**
264
+ * Follows a multi-level pointer chain and returns the resolved absolute address.
265
+ *
266
+ * This helper walks a sequence of offsets starting at `address`, repeatedly
267
+ * dereferencing intermediate pointers as 64-bit unsigned integers, and finally
268
+ * adding the last offset without dereferencing.
269
+ *
270
+ * Semantics:
271
+ * - If `offsets` is empty, the original `address` is returned unchanged.
272
+ * - For each offset except the last, the method adds the offset to the current
273
+ * address and dereferences a `uint64` at that location to get the next base.
274
+ * - If any intermediate dereference yields `0n`:
275
+ * - when `throw_` is `true`, an error is thrown;
276
+ * - otherwise, `-1n` is returned to indicate a null chain.
277
+ * - After all intermediate dereferences succeed, the final offset is **added**
278
+ * (no dereference) and the resulting absolute address is returned.
279
+ *
280
+ * @param address - Starting absolute memory address (BigInt).
281
+ * @param offsets - Readonly list of `bigint` offsets that define the pointer path.
282
+ * @param throw_ - When `true`, throw on a null pointer encounter (default: `false`).
283
+ * @returns The resolved absolute address, or `-1n` if a null pointer was encountered and `throw_` is `false`.
284
+ * @throws {Error} When a null pointer is encountered and `throw_` is `true`.
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * // Typical multi-level pointer chain (moduleBase + 0x123456 → [0x10, 0x20] → +0x30 final)
289
+ * const client = memory.modules['client.dll'];
290
+ * const resolved = memory.follow(client.base, [0x10n, 0x20n, 0x30n]);
291
+ *
292
+ * if (resolved !== -1n) {
293
+ * const health = memory.f32(resolved);
294
+ * console.log('Health:', health);
295
+ * }
296
+ * ```
297
+ */
298
+ public follow(address: bigint, offsets: readonly bigint[], throw_ = false): bigint {
299
+ const last = offsets.length - 1;
300
+
301
+ if (last === -1) {
302
+ return address;
303
+ }
304
+
305
+ for (let i = 0; i < last; i++) {
306
+ address = this.u64((address += offsets[i]));
307
+
308
+ if (address === 0n) {
309
+ if (throw_) {
310
+ throw new Error('address must not be 0n.');
311
+ }
312
+
313
+ return -1n;
314
+ }
315
+ }
316
+
317
+ return address + offsets[last];
318
+ }
319
+
263
320
  /**
264
321
  * Reads data from the target process memory into the provided scratch buffer and returns that
265
322
  * same scratch object (strongly typed). This is a low-level, zero-copy helper used internally by