@mlightcad/data-model 1.10.4 → 1.10.6

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.
Files changed (71) hide show
  1. package/dist/data-model.cjs +12 -11
  2. package/lib/converter/AcDbRegenerator.d.ts +4 -0
  3. package/lib/converter/AcDbRegenerator.d.ts.map +1 -1
  4. package/lib/converter/AcDbRegenerator.js +6 -0
  5. package/lib/converter/AcDbRegenerator.js.map +1 -1
  6. package/lib/database/AcDbClass.d.ts +45 -0
  7. package/lib/database/AcDbClass.d.ts.map +1 -0
  8. package/lib/database/AcDbClass.js +2 -0
  9. package/lib/database/AcDbClass.js.map +1 -0
  10. package/lib/database/AcDbDatabase.d.ts +20 -0
  11. package/lib/database/AcDbDatabase.d.ts.map +1 -1
  12. package/lib/database/AcDbDatabase.js +93 -26
  13. package/lib/database/AcDbDatabase.js.map +1 -1
  14. package/lib/database/AcDbDatabaseConverter.d.ts +1 -0
  15. package/lib/database/AcDbDatabaseConverter.d.ts.map +1 -1
  16. package/lib/database/AcDbDatabaseConverter.js +4 -0
  17. package/lib/database/AcDbDatabaseConverter.js.map +1 -1
  18. package/lib/database/AcDbTextStyleTableRecord.d.ts +7 -0
  19. package/lib/database/AcDbTextStyleTableRecord.d.ts.map +1 -1
  20. package/lib/database/AcDbTextStyleTableRecord.js +22 -1
  21. package/lib/database/AcDbTextStyleTableRecord.js.map +1 -1
  22. package/lib/database/AcDbViewportTableRecord.d.ts +11 -1
  23. package/lib/database/AcDbViewportTableRecord.d.ts.map +1 -1
  24. package/lib/database/AcDbViewportTableRecord.js +33 -5
  25. package/lib/database/AcDbViewportTableRecord.js.map +1 -1
  26. package/lib/database/index.d.ts +1 -0
  27. package/lib/database/index.d.ts.map +1 -1
  28. package/lib/database/index.js.map +1 -1
  29. package/lib/entity/AcDbHatch.d.ts.map +1 -1
  30. package/lib/entity/AcDbHatch.js +5 -2
  31. package/lib/entity/AcDbHatch.js.map +1 -1
  32. package/lib/entity/AcDbMText.d.ts.map +1 -1
  33. package/lib/entity/AcDbMText.js +4 -3
  34. package/lib/entity/AcDbMText.js.map +1 -1
  35. package/lib/entity/AcDbPolyline.d.ts +5 -0
  36. package/lib/entity/AcDbPolyline.d.ts.map +1 -1
  37. package/lib/entity/AcDbPolyline.js +70 -7
  38. package/lib/entity/AcDbPolyline.js.map +1 -1
  39. package/lib/entity/AcDbProxyEntity.d.ts +59 -13
  40. package/lib/entity/AcDbProxyEntity.d.ts.map +1 -1
  41. package/lib/entity/AcDbProxyEntity.js +96 -27
  42. package/lib/entity/AcDbProxyEntity.js.map +1 -1
  43. package/lib/entity/AcDbShape.d.ts +17 -0
  44. package/lib/entity/AcDbShape.d.ts.map +1 -1
  45. package/lib/entity/AcDbShape.js +45 -10
  46. package/lib/entity/AcDbShape.js.map +1 -1
  47. package/lib/entity/AcDbSolid.d.ts +15 -0
  48. package/lib/entity/AcDbSolid.d.ts.map +1 -0
  49. package/lib/entity/AcDbSolid.js +42 -0
  50. package/lib/entity/AcDbSolid.js.map +1 -0
  51. package/lib/entity/AcDbTrace.d.ts +1 -1
  52. package/lib/entity/AcDbTrace.d.ts.map +1 -1
  53. package/lib/entity/AcDbTrace.js +8 -4
  54. package/lib/entity/AcDbTrace.js.map +1 -1
  55. package/lib/entity/index.d.ts +1 -0
  56. package/lib/entity/index.d.ts.map +1 -1
  57. package/lib/entity/index.js +1 -0
  58. package/lib/entity/index.js.map +1 -1
  59. package/lib/index.d.ts +4 -4
  60. package/lib/index.d.ts.map +1 -1
  61. package/lib/index.js +2 -2
  62. package/lib/index.js.map +1 -1
  63. package/lib/misc/AcDbMemoryEstimator.d.ts +115 -0
  64. package/lib/misc/AcDbMemoryEstimator.d.ts.map +1 -0
  65. package/lib/misc/AcDbMemoryEstimator.js +753 -0
  66. package/lib/misc/AcDbMemoryEstimator.js.map +1 -0
  67. package/lib/misc/index.d.ts +2 -0
  68. package/lib/misc/index.d.ts.map +1 -1
  69. package/lib/misc/index.js +1 -0
  70. package/lib/misc/index.js.map +1 -1
  71. package/package.json +4 -4
@@ -0,0 +1,753 @@
1
+ /**
2
+ * @fileoverview Heuristic in-memory size estimator for {@link AcDbDatabase}.
3
+ *
4
+ * Walks the ownership graph with a {@link WeakSet} to avoid cycles and estimates
5
+ * bytes using V8-inspired constants. Results are reproducible and useful for
6
+ * comparing drawings; they are not exact Chrome heap retained sizes.
7
+ * Cross-check with `performance.memory` / DevTools heap snapshots when needed.
8
+ *
9
+ * @module AcDbMemoryEstimator
10
+ */
11
+ var __values = (this && this.__values) || function(o) {
12
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
13
+ if (m) return m.call(o);
14
+ if (o && typeof o.length === "number") return {
15
+ next: function () {
16
+ if (o && i >= o.length) o = void 0;
17
+ return { value: o && o[i++], done: !o };
18
+ }
19
+ };
20
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
21
+ };
22
+ var __read = (this && this.__read) || function (o, n) {
23
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
24
+ if (!m) return o;
25
+ var i = m.call(o), r, ar = [], e;
26
+ try {
27
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
28
+ }
29
+ catch (error) { e = { error: error }; }
30
+ finally {
31
+ try {
32
+ if (r && !r.done && (m = i["return"])) m.call(i);
33
+ }
34
+ finally { if (e) throw e.error; }
35
+ }
36
+ return ar;
37
+ };
38
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
39
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
40
+ if (ar || !(i in from)) {
41
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
42
+ ar[i] = from[i];
43
+ }
44
+ }
45
+ return to.concat(ar || Array.prototype.slice.call(from));
46
+ };
47
+ import { AcDbEntity } from '../entity/AcDbEntity';
48
+ /** Estimated per-object header size in bytes (V8-inspired heuristic). */
49
+ var OBJECT_OVERHEAD = 48;
50
+ /** Estimated pointer / slot size in bytes. */
51
+ var POINTER_SIZE = 8;
52
+ /** Estimated array object header size in bytes. */
53
+ var ARRAY_OVERHEAD = 48;
54
+ /** Estimated `Map` object header size in bytes. */
55
+ var MAP_OVERHEAD = 80;
56
+ /** Estimated cost of one `Map` entry (excluding key/value payloads). */
57
+ var MAP_ENTRY_OVERHEAD = 32;
58
+ /** Estimated `Set` object header size in bytes. */
59
+ var SET_OVERHEAD = 80;
60
+ /** Estimated cost of one `Set` entry (excluding value payload). */
61
+ var SET_ENTRY_OVERHEAD = 24;
62
+ /** Estimated string object header size in bytes (UTF-16 payload billed separately). */
63
+ var STRING_OVERHEAD = 40;
64
+ /** Estimated size of a JavaScript `number`. */
65
+ var NUMBER_SIZE = 8;
66
+ /** Estimated size of a JavaScript `boolean`. */
67
+ var BOOLEAN_SIZE = 4;
68
+ /** Estimated TypedArray / ArrayBuffer object header size in bytes. */
69
+ var TYPED_ARRAY_OVERHEAD = 64;
70
+ /** Estimated `Blob` object header size in bytes (`size` billed separately). */
71
+ var BLOB_OVERHEAD = 64;
72
+ /**
73
+ * {@link AcDbDatabase} own-property names treated as system variables / header
74
+ * state when classifying memory into the `sysvars` category.
75
+ */
76
+ var SYSVAR_KEYS = new Set([
77
+ '_version',
78
+ '_angbase',
79
+ '_angdir',
80
+ '_aunits',
81
+ '_auprec',
82
+ '_lunits',
83
+ '_luprec',
84
+ '_celtscale',
85
+ '_cecolor',
86
+ '_celtype',
87
+ '_celweight',
88
+ '_cetransparency',
89
+ '_clayer',
90
+ '_cmlstyle',
91
+ '_cmlscale',
92
+ '_cmleaderstyle',
93
+ '_hpbackgroundcolor',
94
+ '_hpcolor',
95
+ '_hplayer',
96
+ '_hptransparency',
97
+ '_textstyle',
98
+ '_extents',
99
+ '_insunits',
100
+ '_unitmode',
101
+ '_measurement',
102
+ '_ltscale',
103
+ '_lwdisplay',
104
+ '_pdmode',
105
+ '_pdsize',
106
+ '_osmode',
107
+ '_orthomode',
108
+ '_maxHandle',
109
+ '_drawNoPlotLayers',
110
+ '_dwgname',
111
+ '_currentSpace',
112
+ '_formatter',
113
+ '_eventBatchDepth',
114
+ '_pendingEntityAppended',
115
+ '_pendingEntityErased',
116
+ '_pendingDictObjectSet',
117
+ '_pendingDictObjectErased',
118
+ '_lastOpenError'
119
+ ]);
120
+ /**
121
+ * Property names that are never walked (prototype / call-stack noise).
122
+ */
123
+ var SKIP_ALWAYS = new Set([
124
+ 'constructor',
125
+ 'prototype',
126
+ '__proto__',
127
+ 'caller',
128
+ 'callee',
129
+ 'arguments'
130
+ ]);
131
+ /**
132
+ * Returns the bucket for `key`, creating an empty one when missing.
133
+ *
134
+ * @param map - Category or entity-type bucket map.
135
+ * @param key - Bucket key to look up or create.
136
+ * @returns The existing or newly created bucket.
137
+ * @internal
138
+ */
139
+ function ensureBucket(map, key) {
140
+ var bucket = map.get(key);
141
+ if (!bucket) {
142
+ bucket = { bytes: 0, count: 0 };
143
+ map.set(key, bucket);
144
+ }
145
+ return bucket;
146
+ }
147
+ /**
148
+ * Adds estimated bytes (and optional object count) to a category bucket.
149
+ *
150
+ * No-op when both `bytes` and `objectDelta` are zero.
151
+ *
152
+ * @param state - Shared walk state.
153
+ * @param category - Category name to update.
154
+ * @param bytes - Bytes to add to the category.
155
+ * @param objectDelta - Object count delta to add (default `0`).
156
+ * @internal
157
+ */
158
+ function addBytes(state, category, bytes, objectDelta) {
159
+ if (objectDelta === void 0) { objectDelta = 0; }
160
+ if (bytes <= 0 && objectDelta === 0)
161
+ return;
162
+ var bucket = ensureBucket(state.byCategory, category);
163
+ bucket.bytes += bytes;
164
+ bucket.count += objectDelta;
165
+ }
166
+ /**
167
+ * Returns whether `value` is a plain object (`Object` prototype or `null`
168
+ * prototype), as opposed to a class instance.
169
+ *
170
+ * @param value - Object to test.
171
+ * @returns `true` when `value` is a plain object.
172
+ * @internal
173
+ */
174
+ function isPlainObject(value) {
175
+ var proto = Object.getPrototypeOf(value);
176
+ return proto === Object.prototype || proto === null;
177
+ }
178
+ /**
179
+ * Type guard for TypedArray / DataView values (`ArrayBuffer.isView`).
180
+ *
181
+ * @param value - Value to test.
182
+ * @returns `true` when `value` is an {@link ArrayBufferView}.
183
+ * @internal
184
+ */
185
+ function isTypedArray(value) {
186
+ return ArrayBuffer.isView(value);
187
+ }
188
+ /**
189
+ * Heuristic detection of {@link AcCmEventManager}-like objects so their
190
+ * listener lists can be skipped when event managers are excluded.
191
+ *
192
+ * @param value - Object to test.
193
+ * @returns `true` when `value` looks like an event manager.
194
+ * @internal
195
+ */
196
+ function isAcCmEventManager(value) {
197
+ return (typeof value.addEventListener ===
198
+ 'function' &&
199
+ typeof value.dispatch === 'function' &&
200
+ 'listeners' in value);
201
+ }
202
+ /**
203
+ * Returns whether a property should be skipped based on walk options and
204
+ * always-skipped names.
205
+ *
206
+ * @param state - Shared walk state (options).
207
+ * @param key - Property name being considered.
208
+ * @param category - Current ownership category of the parent object.
209
+ * @returns `true` when the property must not be walked.
210
+ * @internal
211
+ */
212
+ function shouldSkipProperty(state, key, category) {
213
+ if (SKIP_ALWAYS.has(key))
214
+ return true;
215
+ if (!state.includeEventManagers &&
216
+ (key === 'events' || category === 'events')) {
217
+ return key === 'events';
218
+ }
219
+ if (!state.includeTransactionManager &&
220
+ (key === 'transactionManager' || category === 'transaction')) {
221
+ return key === 'transactionManager';
222
+ }
223
+ return false;
224
+ }
225
+ /**
226
+ * Resolves the ownership category for a child value based on the parent
227
+ * category, property name, and runtime type.
228
+ *
229
+ * @param parentCategory - Category of the owning object.
230
+ * @param key - Child property name (or array index as string).
231
+ * @param value - Child value (used for entity detection).
232
+ * @returns Category to use when measuring the child.
233
+ * @internal
234
+ */
235
+ function resolveChildCategory(parentCategory, key, value) {
236
+ if (key === '_xDataMap' || parentCategory === 'xdata') {
237
+ return 'xdata';
238
+ }
239
+ if (key === '_tables' || parentCategory === 'tables') {
240
+ if (value instanceof AcDbEntity)
241
+ return 'entities';
242
+ return 'tables';
243
+ }
244
+ if (key === '_entities' || parentCategory === 'entities') {
245
+ return 'entities';
246
+ }
247
+ if (key === '_objects' || parentCategory === 'objects') {
248
+ return 'objects';
249
+ }
250
+ if (key === '_handleRegistry' || parentCategory === 'handleRegistry') {
251
+ return 'handleRegistry';
252
+ }
253
+ if (key === 'transactionManager' || parentCategory === 'transaction') {
254
+ return 'transaction';
255
+ }
256
+ if (key === 'events' || parentCategory === 'events') {
257
+ return 'events';
258
+ }
259
+ if (parentCategory === 'sysvars' || SYSVAR_KEYS.has(key)) {
260
+ return 'sysvars';
261
+ }
262
+ if (value instanceof AcDbEntity) {
263
+ return 'entities';
264
+ }
265
+ return parentCategory === 'other' ? 'other' : parentCategory;
266
+ }
267
+ /**
268
+ * Collects instance data property names from `obj` and its class prototype
269
+ * chain (TypeScript `private` fields are still present as `_foo` on the
270
+ * instance / class field storage).
271
+ *
272
+ * Skips methods, accessors without a data value, and built-in prototypes
273
+ * such as `Array.prototype`.
274
+ *
275
+ * @param obj - Class instance or plain object to inspect.
276
+ * @returns Deduplicated list of instance property names.
277
+ * @internal
278
+ */
279
+ function collectInstanceKeys(obj) {
280
+ var e_1, _a;
281
+ var keys = new Set();
282
+ var current = obj;
283
+ while (current && current !== Object.prototype) {
284
+ try {
285
+ for (var _b = (e_1 = void 0, __values(Object.getOwnPropertyNames(current))), _c = _b.next(); !_c.done; _c = _b.next()) {
286
+ var key = _c.value;
287
+ if (SKIP_ALWAYS.has(key))
288
+ continue;
289
+ // Skip prototype methods; we only want instance data fields.
290
+ var desc = Object.getOwnPropertyDescriptor(current, key);
291
+ if (desc && typeof desc.value === 'function')
292
+ continue;
293
+ if (desc && (desc.get || desc.set) && desc.value === undefined)
294
+ continue;
295
+ keys.add(key);
296
+ }
297
+ }
298
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
299
+ finally {
300
+ try {
301
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
302
+ }
303
+ finally { if (e_1) throw e_1.error; }
304
+ }
305
+ current = Object.getPrototypeOf(current);
306
+ // Stop before walking built-in prototypes for class instances that store
307
+ // data only on the instance / custom prototypes above Object.
308
+ if (current === Object.prototype || current === null)
309
+ break;
310
+ // For arrays/maps, own keys on the instance are enough; avoid Array.prototype.
311
+ if (current === Array.prototype ||
312
+ current === Map.prototype ||
313
+ current === Set.prototype) {
314
+ break;
315
+ }
316
+ }
317
+ return __spreadArray([], __read(keys), false);
318
+ }
319
+ /**
320
+ * Estimates the size of a primitive value (number, boolean, string, bigint,
321
+ * or symbol). Returns `0` for `null`, `undefined`, and non-primitives.
322
+ *
323
+ * @param value - Value to measure.
324
+ * @returns Estimated size in bytes.
325
+ * @internal
326
+ */
327
+ function measurePrimitive(value) {
328
+ var _a;
329
+ if (value === null || value === undefined)
330
+ return 0;
331
+ switch (typeof value) {
332
+ case 'number':
333
+ return NUMBER_SIZE;
334
+ case 'boolean':
335
+ return BOOLEAN_SIZE;
336
+ case 'string':
337
+ return STRING_OVERHEAD + value.length * 2;
338
+ case 'bigint':
339
+ return 16;
340
+ case 'symbol':
341
+ return STRING_OVERHEAD + String((_a = value.description) !== null && _a !== void 0 ? _a : '').length * 2;
342
+ default:
343
+ return 0;
344
+ }
345
+ }
346
+ /**
347
+ * Measures only the structure of the database handle registry `Map`
348
+ * (header, entry slots, and key strings). Registered object values are
349
+ * expected to be counted via the ownership graph instead.
350
+ *
351
+ * @param state - Shared walk state.
352
+ * @param registry - The database `_handleRegistry` map.
353
+ * @returns Estimated registry overhead in bytes, or `0` if already visited.
354
+ * @internal
355
+ */
356
+ function measureHandleRegistryOverhead(state, registry) {
357
+ var e_2, _a;
358
+ if (state.visited.has(registry))
359
+ return 0;
360
+ state.visited.add(registry);
361
+ state.objectCount += 1;
362
+ // Objects are counted via the ownership graph; only Map structure + keys.
363
+ var bytes = MAP_OVERHEAD + registry.size * MAP_ENTRY_OVERHEAD;
364
+ try {
365
+ for (var _b = __values(registry.keys()), _c = _b.next(); !_c.done; _c = _b.next()) {
366
+ var key = _c.value;
367
+ bytes += measurePrimitive(key);
368
+ }
369
+ }
370
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
371
+ finally {
372
+ try {
373
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
374
+ }
375
+ finally { if (e_2) throw e_2.error; }
376
+ }
377
+ addBytes(state, 'handleRegistry', bytes, 1);
378
+ return bytes;
379
+ }
380
+ /**
381
+ * Recursively walks a value, attributing estimated bytes to the current
382
+ * category and optional entity type. Uses {@link WalkState.visited} to avoid
383
+ * recounting shared or cyclic references.
384
+ *
385
+ * @param state - Shared walk state.
386
+ * @param value - Value to measure.
387
+ * @param category - Ownership category for this value.
388
+ * @param entityType - Active entity type name when walking entity payload,
389
+ * or `null` when outside an entity.
390
+ * @returns Estimated size in bytes for this subtree (also recorded in `state`).
391
+ * @internal
392
+ */
393
+ function walkValue(state, value, category, entityType) {
394
+ var e_3, _a, e_4, _b, e_5, _c, e_6, _d;
395
+ if (value === null || value === undefined)
396
+ return 0;
397
+ var valueType = typeof value;
398
+ if (valueType === 'function')
399
+ return 0;
400
+ if (valueType !== 'object') {
401
+ var bytes_1 = measurePrimitive(value);
402
+ addBytes(state, category, bytes_1);
403
+ if (entityType) {
404
+ var bucket = ensureBucket(state.byEntityType, entityType);
405
+ bucket.bytes += bytes_1;
406
+ }
407
+ return bytes_1;
408
+ }
409
+ var obj = value;
410
+ // DOM / host objects
411
+ if (typeof obj.nodeType === 'number')
412
+ return 0;
413
+ if (state.visited.has(obj))
414
+ return 0;
415
+ state.visited.add(obj);
416
+ state.objectCount += 1;
417
+ if (!state.includeEventManagers && isAcCmEventManager(obj)) {
418
+ addBytes(state, category, OBJECT_OVERHEAD, 1);
419
+ return OBJECT_OVERHEAD;
420
+ }
421
+ var localEntityType = entityType;
422
+ var localCategory = category;
423
+ var isEntity = false;
424
+ if (obj instanceof AcDbEntity) {
425
+ isEntity = true;
426
+ localCategory = 'entities';
427
+ localEntityType = obj.type;
428
+ state.entityCount += 1;
429
+ var typeBucket = ensureBucket(state.byEntityType, localEntityType);
430
+ typeBucket.count += 1;
431
+ }
432
+ // Promise
433
+ if (typeof obj.then === 'function') {
434
+ addBytes(state, localCategory, OBJECT_OVERHEAD, 1);
435
+ return OBJECT_OVERHEAD;
436
+ }
437
+ // ArrayBuffer
438
+ if (obj instanceof ArrayBuffer) {
439
+ var bytes_2 = TYPED_ARRAY_OVERHEAD + obj.byteLength;
440
+ addBytes(state, localCategory, bytes_2, 1);
441
+ if (localEntityType) {
442
+ ensureBucket(state.byEntityType, localEntityType).bytes += bytes_2;
443
+ }
444
+ return bytes_2;
445
+ }
446
+ // TypedArray / DataView
447
+ if (isTypedArray(obj)) {
448
+ var bytes_3 = TYPED_ARRAY_OVERHEAD + obj.byteLength;
449
+ // Count underlying buffer only once via visited set when shared.
450
+ if (obj.buffer && !state.visited.has(obj.buffer)) {
451
+ state.visited.add(obj.buffer);
452
+ }
453
+ addBytes(state, localCategory, bytes_3, 1);
454
+ if (localEntityType) {
455
+ ensureBucket(state.byEntityType, localEntityType).bytes += bytes_3;
456
+ }
457
+ return bytes_3;
458
+ }
459
+ // Blob
460
+ if (typeof Blob !== 'undefined' && obj instanceof Blob) {
461
+ var bytes_4 = BLOB_OVERHEAD + obj.size;
462
+ addBytes(state, localCategory, bytes_4, 1);
463
+ if (localEntityType) {
464
+ ensureBucket(state.byEntityType, localEntityType).bytes += bytes_4;
465
+ }
466
+ return bytes_4;
467
+ }
468
+ // Date
469
+ if (obj instanceof Date) {
470
+ var bytes_5 = OBJECT_OVERHEAD + 8;
471
+ addBytes(state, localCategory, bytes_5, 1);
472
+ return bytes_5;
473
+ }
474
+ // Map — special-case handle registry values (already counted via ownership)
475
+ if (obj instanceof Map) {
476
+ var isHandleRegistry = localCategory === 'handleRegistry';
477
+ var structureBytes = MAP_OVERHEAD + obj.size * MAP_ENTRY_OVERHEAD;
478
+ var bytes_6 = structureBytes;
479
+ addBytes(state, localCategory, structureBytes, 1);
480
+ if (localEntityType) {
481
+ ensureBucket(state.byEntityType, localEntityType).bytes += structureBytes;
482
+ }
483
+ try {
484
+ for (var obj_1 = __values(obj), obj_1_1 = obj_1.next(); !obj_1_1.done; obj_1_1 = obj_1.next()) {
485
+ var _e = __read(obj_1_1.value, 2), k = _e[0], v = _e[1];
486
+ bytes_6 += walkValue(state, k, localCategory, localEntityType);
487
+ if (!isHandleRegistry) {
488
+ bytes_6 += walkValue(state, v, localCategory, localEntityType);
489
+ }
490
+ }
491
+ }
492
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
493
+ finally {
494
+ try {
495
+ if (obj_1_1 && !obj_1_1.done && (_a = obj_1.return)) _a.call(obj_1);
496
+ }
497
+ finally { if (e_3) throw e_3.error; }
498
+ }
499
+ return bytes_6;
500
+ }
501
+ // Set
502
+ if (obj instanceof Set) {
503
+ var bytes_7 = SET_OVERHEAD + obj.size * SET_ENTRY_OVERHEAD;
504
+ try {
505
+ for (var obj_2 = __values(obj), obj_2_1 = obj_2.next(); !obj_2_1.done; obj_2_1 = obj_2.next()) {
506
+ var item = obj_2_1.value;
507
+ bytes_7 += walkValue(state, item, localCategory, localEntityType);
508
+ }
509
+ }
510
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
511
+ finally {
512
+ try {
513
+ if (obj_2_1 && !obj_2_1.done && (_b = obj_2.return)) _b.call(obj_2);
514
+ }
515
+ finally { if (e_4) throw e_4.error; }
516
+ }
517
+ addBytes(state, localCategory, SET_OVERHEAD + obj.size * SET_ENTRY_OVERHEAD, 1);
518
+ if (localEntityType) {
519
+ ensureBucket(state.byEntityType, localEntityType).bytes +=
520
+ SET_OVERHEAD + obj.size * SET_ENTRY_OVERHEAD;
521
+ }
522
+ return bytes_7;
523
+ }
524
+ // Array
525
+ if (Array.isArray(obj)) {
526
+ var bytes_8 = ARRAY_OVERHEAD + obj.length * POINTER_SIZE;
527
+ addBytes(state, localCategory, bytes_8, 1);
528
+ if (localEntityType) {
529
+ ensureBucket(state.byEntityType, localEntityType).bytes += bytes_8;
530
+ }
531
+ for (var i = 0; i < obj.length; i++) {
532
+ var child = obj[i];
533
+ var childCategory = resolveChildCategory(localCategory, String(i), child);
534
+ bytes_8 += walkValue(state, child, childCategory, localEntityType);
535
+ }
536
+ return bytes_8;
537
+ }
538
+ // Generic object / class instance
539
+ var bytes = OBJECT_OVERHEAD;
540
+ var keys = isPlainObject(obj)
541
+ ? Object.getOwnPropertyNames(obj)
542
+ : collectInstanceKeys(obj);
543
+ try {
544
+ // Property name strings + pointer slots
545
+ for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
546
+ var key = keys_1_1.value;
547
+ bytes += POINTER_SIZE;
548
+ // Hidden class / property name cost amortized; count key string once lightly
549
+ bytes += Math.min(STRING_OVERHEAD + key.length * 2, 64);
550
+ }
551
+ }
552
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
553
+ finally {
554
+ try {
555
+ if (keys_1_1 && !keys_1_1.done && (_c = keys_1.return)) _c.call(keys_1);
556
+ }
557
+ finally { if (e_5) throw e_5.error; }
558
+ }
559
+ addBytes(state, localCategory, bytes, 1);
560
+ if (localEntityType) {
561
+ ensureBucket(state.byEntityType, localEntityType).bytes += bytes;
562
+ }
563
+ if (isEntity) {
564
+ // Entity count already incremented; category count for entities tracks objects
565
+ }
566
+ try {
567
+ for (var keys_2 = __values(keys), keys_2_1 = keys_2.next(); !keys_2_1.done; keys_2_1 = keys_2.next()) {
568
+ var key = keys_2_1.value;
569
+ if (shouldSkipProperty(state, key, localCategory))
570
+ continue;
571
+ // Avoid walking back to owning database through private refs (cycle).
572
+ if (key === '_database' || key === 'database')
573
+ continue;
574
+ var child = void 0;
575
+ try {
576
+ child = obj[key];
577
+ }
578
+ catch (_f) {
579
+ continue;
580
+ }
581
+ if (typeof child === 'function')
582
+ continue;
583
+ // Dedicated handle-registry path: structure only
584
+ if (key === '_handleRegistry' && child instanceof Map) {
585
+ bytes += measureHandleRegistryOverhead(state, child);
586
+ continue;
587
+ }
588
+ var childCategory = resolveChildCategory(localCategory, key, child);
589
+ if (!state.includeTransactionManager &&
590
+ childCategory === 'transaction') {
591
+ continue;
592
+ }
593
+ if (!state.includeEventManagers && childCategory === 'events') {
594
+ continue;
595
+ }
596
+ bytes += walkValue(state, child, childCategory, localEntityType);
597
+ }
598
+ }
599
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
600
+ finally {
601
+ try {
602
+ if (keys_2_1 && !keys_2_1.done && (_d = keys_2.return)) _d.call(keys_2);
603
+ }
604
+ finally { if (e_6) throw e_6.error; }
605
+ }
606
+ return bytes;
607
+ }
608
+ /**
609
+ * Estimates the in-memory footprint of an {@link AcDbDatabase} by walking its
610
+ * ownership graph and applying V8-inspired size heuristics.
611
+ *
612
+ * The estimate is reproducible and suitable for comparing drawings. It is not
613
+ * an exact Chrome / V8 heap retained size; expect roughly ±20–30% versus
614
+ * DevTools heap snapshots. Rendering GPU buffers and converter worker / WASM
615
+ * heaps are not included.
616
+ *
617
+ * @param db - Drawing database to measure (typically after `read` / `openUri`).
618
+ * @param options - Optional inclusion of transaction / event graphs.
619
+ * @returns Structured estimate with category and entity-type breakdowns.
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * const report = acdbEstimateDatabaseMemory(database)
624
+ * console.log(acdbFormatMemoryEstimate(report))
625
+ * ```
626
+ */
627
+ export function acdbEstimateDatabaseMemory(db, options) {
628
+ var e_7, _a, e_8, _b;
629
+ var state = {
630
+ visited: new WeakSet(),
631
+ objectCount: 0,
632
+ entityCount: 0,
633
+ byCategory: new Map(),
634
+ byEntityType: new Map(),
635
+ includeTransactionManager: (options === null || options === void 0 ? void 0 : options.includeTransactionManager) === true,
636
+ includeEventManagers: (options === null || options === void 0 ? void 0 : options.includeEventManagers) === true
637
+ };
638
+ // Root walk starts as sysvars for db-owned scalars; tables/objects keys
639
+ // reclassify via resolveChildCategory.
640
+ walkValue(state, db, 'sysvars', null);
641
+ var totalBytes = 0;
642
+ var byCategory = {};
643
+ try {
644
+ for (var _c = __values(state.byCategory), _d = _c.next(); !_d.done; _d = _c.next()) {
645
+ var _e = __read(_d.value, 2), key = _e[0], bucket = _e[1];
646
+ byCategory[key] = { bytes: bucket.bytes, count: bucket.count };
647
+ totalBytes += bucket.bytes;
648
+ }
649
+ }
650
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
651
+ finally {
652
+ try {
653
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
654
+ }
655
+ finally { if (e_7) throw e_7.error; }
656
+ }
657
+ var byEntityType = {};
658
+ try {
659
+ for (var _f = __values(state.byEntityType), _g = _f.next(); !_g.done; _g = _f.next()) {
660
+ var _h = __read(_g.value, 2), key = _h[0], bucket = _h[1];
661
+ byEntityType[key] = { bytes: bucket.bytes, count: bucket.count };
662
+ }
663
+ }
664
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
665
+ finally {
666
+ try {
667
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
668
+ }
669
+ finally { if (e_8) throw e_8.error; }
670
+ }
671
+ return {
672
+ totalBytes: totalBytes,
673
+ objectCount: state.objectCount,
674
+ entityCount: state.entityCount,
675
+ byCategory: byCategory,
676
+ byEntityType: byEntityType
677
+ };
678
+ }
679
+ /**
680
+ * Formats a byte count as a short human-readable string using binary units
681
+ * (`B`, `KiB`, or `MiB`).
682
+ *
683
+ * @param bytes - Non-negative byte count to format.
684
+ * @returns Formatted size string, for example `"512 B"` or `"2.00 KiB"`.
685
+ *
686
+ * @example
687
+ * ```typescript
688
+ * acdbFormatMemoryBytes(512) // "512 B"
689
+ * acdbFormatMemoryBytes(2048) // "2.00 KiB"
690
+ * ```
691
+ */
692
+ export function acdbFormatMemoryBytes(bytes) {
693
+ if (bytes < 1024)
694
+ return "".concat(bytes, " B");
695
+ if (bytes < 1024 * 1024)
696
+ return "".concat((bytes / 1024).toFixed(2), " KiB");
697
+ return "".concat((bytes / (1024 * 1024)).toFixed(2), " MiB");
698
+ }
699
+ /**
700
+ * Formats an {@link AcDbMemoryEstimate} as multi-line text for console or UI
701
+ * output, including totals plus category and entity-type breakdowns sorted by
702
+ * descending byte size.
703
+ *
704
+ * @param report - Estimate produced by {@link acdbEstimateDatabaseMemory}.
705
+ * @returns Human-readable multi-line summary string.
706
+ *
707
+ * @example
708
+ * ```typescript
709
+ * const report = acdbEstimateDatabaseMemory(database)
710
+ * console.log(acdbFormatMemoryEstimate(report))
711
+ * ```
712
+ */
713
+ export function acdbFormatMemoryEstimate(report) {
714
+ var e_9, _a, e_10, _b;
715
+ var lines = [
716
+ "AcDbDatabase memory estimate: ".concat(acdbFormatMemoryBytes(report.totalBytes), " (").concat(report.totalBytes, " bytes)"),
717
+ "Objects: ".concat(report.objectCount, ", Entities: ").concat(report.entityCount),
718
+ 'By category:'
719
+ ];
720
+ var categories = Object.entries(report.byCategory).sort(function (a, b) { return b[1].bytes - a[1].bytes; });
721
+ try {
722
+ for (var categories_1 = __values(categories), categories_1_1 = categories_1.next(); !categories_1_1.done; categories_1_1 = categories_1.next()) {
723
+ var _c = __read(categories_1_1.value, 2), name_1 = _c[0], bucket = _c[1];
724
+ lines.push(" ".concat(name_1, ": ").concat(acdbFormatMemoryBytes(bucket.bytes), " (").concat(bucket.bytes, " bytes), count=").concat(bucket.count));
725
+ }
726
+ }
727
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
728
+ finally {
729
+ try {
730
+ if (categories_1_1 && !categories_1_1.done && (_a = categories_1.return)) _a.call(categories_1);
731
+ }
732
+ finally { if (e_9) throw e_9.error; }
733
+ }
734
+ var entityTypes = Object.entries(report.byEntityType).sort(function (a, b) { return b[1].bytes - a[1].bytes; });
735
+ if (entityTypes.length > 0) {
736
+ lines.push('By entity type:');
737
+ try {
738
+ for (var entityTypes_1 = __values(entityTypes), entityTypes_1_1 = entityTypes_1.next(); !entityTypes_1_1.done; entityTypes_1_1 = entityTypes_1.next()) {
739
+ var _d = __read(entityTypes_1_1.value, 2), name_2 = _d[0], bucket = _d[1];
740
+ lines.push(" ".concat(name_2, ": ").concat(acdbFormatMemoryBytes(bucket.bytes), " (").concat(bucket.bytes, " bytes), count=").concat(bucket.count));
741
+ }
742
+ }
743
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
744
+ finally {
745
+ try {
746
+ if (entityTypes_1_1 && !entityTypes_1_1.done && (_b = entityTypes_1.return)) _b.call(entityTypes_1);
747
+ }
748
+ finally { if (e_10) throw e_10.error; }
749
+ }
750
+ }
751
+ return lines.join('\n');
752
+ }
753
+ //# sourceMappingURL=AcDbMemoryEstimator.js.map