eyeprolog 1.2.27 → 1.2.28

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.2.27",
6
+ "version": "1.2.28",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/platform.js CHANGED
@@ -15,6 +15,8 @@ if (isNode) {
15
15
  BufferCtor = globalThis.Buffer ?? null;
16
16
  }
17
17
 
18
+ const configuredOldSpaceLimit = configuredOldSpaceBytes();
19
+
18
20
  export { fs, path, BufferCtor, isNode };
19
21
 
20
22
  export function currentWorkingDirectory() {
@@ -23,6 +25,17 @@ export function currentWorkingDirectory() {
23
25
 
24
26
  export function usedHeapSize() {
25
27
  if (isNode && typeof process.memoryUsage === 'function') {
28
+ // --max-old-space-size constrains V8's old generation, not the complete
29
+ // heap reported by process.memoryUsage().heapUsed. Comparing that limit
30
+ // with total heap use makes bursts of collectible new-space objects look
31
+ // like retained memory. Measure the corresponding non-young spaces when
32
+ // an old-space limit was supplied.
33
+ if (configuredOldSpaceLimit != null && typeof v8?.getHeapSpaceStatistics === 'function') {
34
+ const spaces = v8.getHeapSpaceStatistics();
35
+ return spaces
36
+ .filter(({ space_name: name }) => name !== 'read_only_space' && !name.startsWith('new_'))
37
+ .reduce((total, { space_used_size: size }) => total + size, 0);
38
+ }
26
39
  return process.memoryUsage().heapUsed;
27
40
  }
28
41
  const memory = globalThis.performance?.memory;
@@ -33,8 +46,7 @@ export function softHeapLimit() {
33
46
  let limit = null;
34
47
  if (isNode) {
35
48
  limit = v8?.getHeapStatistics?.().heap_size_limit ?? null;
36
- const configuredOldSpace = configuredOldSpaceBytes();
37
- if (configuredOldSpace != null) limit = Math.min(limit ?? Infinity, configuredOldSpace);
49
+ if (configuredOldSpaceLimit != null) limit = Math.min(limit ?? Infinity, configuredOldSpaceLimit);
38
50
  } else {
39
51
  const memory = globalThis.performance?.memory;
40
52
  if (Number.isFinite(memory?.jsHeapSizeLimit)) limit = memory.jsHeapSizeLimit;
@@ -2586,6 +2586,42 @@ open(X) :- candidate(X), \\+ closed(X).
2586
2586
  assertEqual(result.stdout, '300000', 'fresh-variable answer count');
2587
2587
  },
2588
2588
  },
2589
+ {
2590
+ name: 'caught number syntax errors do not exhaust memory on distinct inputs',
2591
+ run: () => {
2592
+ const engineUrl = new URL('../src/index.js', import.meta.url).href;
2593
+ const programText = `
2594
+ :- use_module(library(lists)).
2595
+ alphabet(['0','1','2','3','4','5','6','7','8','9','.']).
2596
+ trial([A,B,C,D,E]) :-
2597
+ alphabet(Chars),
2598
+ member(A, Chars), member(B, Chars), member(C, Chars),
2599
+ member(D, Chars), member(E, Chars),
2600
+ catch(number_chars(_, [A,B,C,D,E]), error(syntax_error(number), _), true).
2601
+ `;
2602
+ const script = `
2603
+ import { Program, Solver, Env, parseGoalText, getEyePrologRegistry } from ${JSON.stringify(engineUrl)};
2604
+ const program = Program.parse(${JSON.stringify(programText)});
2605
+ const solver = new Solver(program, { registry: getEyePrologRegistry() });
2606
+ const goal = parseGoalText('trial(Chars)');
2607
+ let count = 0;
2608
+ for (const _ of solver.solve([goal], new Env(), 0)) {
2609
+ if (++count === 150000) break;
2610
+ }
2611
+ if (count !== 150000) throw new Error('unexpected answer count: ' + count);
2612
+ process.stdout.write(String(count));
2613
+ `;
2614
+ const result = spawnSync(process.execPath, [
2615
+ '--max-old-space-size=64',
2616
+ '--input-type=module',
2617
+ '--eval',
2618
+ script,
2619
+ ], { cwd: packageRoot, encoding: 'utf8', timeout: 30000 });
2620
+ if (result.error) throw result.error;
2621
+ assertEqual(result.status, 0, `bounded-heap child status; stderr=${result.stderr}`);
2622
+ assertEqual(result.stdout, '150000', 'distinct number syntax attempts');
2623
+ },
2624
+ },
2589
2625
  {
2590
2626
  name: 'host Map/Set capacity errors become resource_error(memory)',
2591
2627
  run: () => {