@ricsam/formula-engine 0.2.9 → 0.2.10

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 (41) hide show
  1. package/README.md +40 -0
  2. package/dist/cjs/core/engine.cjs +37 -1
  3. package/dist/cjs/core/engine.cjs.map +3 -3
  4. package/dist/cjs/core/managers/dependency-manager.cjs +151 -67
  5. package/dist/cjs/core/managers/dependency-manager.cjs.map +3 -3
  6. package/dist/cjs/core/managers/workbook-manager.cjs +197 -1
  7. package/dist/cjs/core/managers/workbook-manager.cjs.map +3 -3
  8. package/dist/cjs/core/types.cjs.map +2 -2
  9. package/dist/cjs/core/workbook-renamer.cjs.map +1 -1
  10. package/dist/cjs/evaluator/formula-evaluator.cjs +22 -48
  11. package/dist/cjs/evaluator/formula-evaluator.cjs.map +3 -3
  12. package/dist/cjs/functions/math/sum/summation-utils.cjs +2 -2
  13. package/dist/cjs/functions/math/sum/summation-utils.cjs.map +2 -2
  14. package/dist/cjs/package.json +1 -1
  15. package/dist/cjs/parser/formatter.cjs +3 -4
  16. package/dist/cjs/parser/formatter.cjs.map +3 -3
  17. package/dist/cjs/parser/parser.cjs +24 -216
  18. package/dist/cjs/parser/parser.cjs.map +3 -3
  19. package/dist/mjs/core/engine.mjs +37 -1
  20. package/dist/mjs/core/engine.mjs.map +3 -3
  21. package/dist/mjs/core/managers/dependency-manager.mjs +151 -67
  22. package/dist/mjs/core/managers/dependency-manager.mjs.map +3 -3
  23. package/dist/mjs/core/managers/workbook-manager.mjs +197 -1
  24. package/dist/mjs/core/managers/workbook-manager.mjs.map +3 -3
  25. package/dist/mjs/core/types.mjs.map +2 -2
  26. package/dist/mjs/core/workbook-renamer.mjs.map +1 -1
  27. package/dist/mjs/evaluator/formula-evaluator.mjs +22 -48
  28. package/dist/mjs/evaluator/formula-evaluator.mjs.map +3 -3
  29. package/dist/mjs/functions/math/sum/summation-utils.mjs +2 -2
  30. package/dist/mjs/functions/math/sum/summation-utils.mjs.map +2 -2
  31. package/dist/mjs/package.json +1 -1
  32. package/dist/mjs/parser/formatter.mjs +3 -4
  33. package/dist/mjs/parser/formatter.mjs.map +3 -3
  34. package/dist/mjs/parser/parser.mjs +24 -216
  35. package/dist/mjs/parser/parser.mjs.map +3 -3
  36. package/dist/types/core/engine.d.ts +15 -1
  37. package/dist/types/core/managers/dependency-manager.d.ts +4 -0
  38. package/dist/types/core/managers/workbook-manager.d.ts +23 -1
  39. package/dist/types/core/types.d.ts +35 -0
  40. package/dist/types/parser/parser.d.ts +4 -6
  41. package/package.json +1 -1
@@ -74,6 +74,49 @@ class DependencyManager {
74
74
  this.cacheManager = cacheManager;
75
75
  this.workbookManager = workbookManager;
76
76
  }
77
+ getSnapshotEligibilityState(node) {
78
+ if (node instanceof import_resource_dependency_node.ResourceDependencyNode) {
79
+ return {
80
+ eligible: true,
81
+ reason: "resource nodes are always snapshot eligible"
82
+ };
83
+ }
84
+ if (node instanceof import_range_evaluation_node.RangeEvaluationNode) {
85
+ return node.result.type === "awaiting-evaluation" ? {
86
+ eligible: false,
87
+ reason: "range result is still awaiting evaluation"
88
+ } : {
89
+ eligible: true,
90
+ reason: `range result type is ${node.result.type}`
91
+ };
92
+ }
93
+ return node.evaluationResult.type === "awaiting-evaluation" ? {
94
+ eligible: false,
95
+ reason: "evaluation result is still awaiting evaluation"
96
+ } : {
97
+ eligible: true,
98
+ reason: `evaluation result type is ${node.evaluationResult.type}`
99
+ };
100
+ }
101
+ logSnapshotRestoreWarning(message, payload) {
102
+ console.warn("[FormulaEngine snapshot]", message, payload);
103
+ }
104
+ getLogicalNodeSnapshotId(node) {
105
+ if (node instanceof import_ast_evaluation_node.AstEvaluationNode) {
106
+ return import_engine_snapshot.getAstNodeSnapshotId(node);
107
+ }
108
+ return node.key;
109
+ }
110
+ resetRestoredNodeToColdState(node) {
111
+ this.unregisterNode(node);
112
+ if (node instanceof import_resource_dependency_node.ResourceDependencyNode) {
113
+ return;
114
+ }
115
+ if (node instanceof import_cell_value_node.CellValueNode) {
116
+ node.clearSpillMetaNode();
117
+ }
118
+ node.invalidate();
119
+ }
77
120
  getSheetWatcherKey(address) {
78
121
  return `${address.workbookName}:${address.sheetName}`;
79
122
  }
@@ -381,13 +424,7 @@ class DependencyManager {
381
424
  }
382
425
  toSnapshot(evaluationManager) {
383
426
  const isNodeSnapshotEligible = (node) => {
384
- if (node instanceof import_resource_dependency_node.ResourceDependencyNode) {
385
- return true;
386
- }
387
- if (node instanceof import_range_evaluation_node.RangeEvaluationNode) {
388
- return node.result.type !== "awaiting-evaluation";
389
- }
390
- return node.evaluationResult.type !== "awaiting-evaluation";
427
+ return this.getSnapshotEligibilityState(node).eligible;
391
428
  };
392
429
  const astNodes = new Set;
393
430
  for (const astEntries of this.asts.values()) {
@@ -425,15 +462,17 @@ class DependencyManager {
425
462
  }
426
463
  const resolvedNodes = Array.from(resolvedNodesSet);
427
464
  const allNodeSnapshotIds = new Map;
465
+ const availableSnapshotIds = new Set;
428
466
  for (const node of resolvedNodes) {
429
- if (node instanceof import_ast_evaluation_node.AstEvaluationNode) {
430
- allNodeSnapshotIds.set(node, import_engine_snapshot.getAstNodeSnapshotId(node));
431
- } else {
432
- allNodeSnapshotIds.set(node, node.key);
433
- }
434
- }
435
- const getAllNodeSnapshotId = (node) => {
436
- const snapshotId = allNodeSnapshotIds.get(node);
467
+ const snapshotId = this.getLogicalNodeSnapshotId(node);
468
+ allNodeSnapshotIds.set(node, snapshotId);
469
+ availableSnapshotIds.add(snapshotId);
470
+ }
471
+ const getAllNodeSnapshotId = (node, _context) => {
472
+ const snapshotId = allNodeSnapshotIds.get(node) ?? (() => {
473
+ const logicalSnapshotId = this.getLogicalNodeSnapshotId(node);
474
+ return availableSnapshotIds.has(logicalSnapshotId) ? logicalSnapshotId : undefined;
475
+ })();
437
476
  if (!snapshotId) {
438
477
  throw new Error(`Missing snapshot id for dependency node ${node.key}`);
439
478
  }
@@ -479,9 +518,25 @@ class DependencyManager {
479
518
  restoreFromSnapshot(snapshots, evaluationManager) {
480
519
  this.clearEvaluationCache();
481
520
  const nodesBySnapshotId = new Map;
521
+ let hadRestoreFailures = false;
482
522
  for (const snapshot of snapshots.dependency.nodes) {
483
- const node = this.createNodeFromSnapshot(snapshot);
484
- nodesBySnapshotId.set(snapshot.snapshotId, node);
523
+ try {
524
+ const node = this.createNodeFromSnapshot(snapshot);
525
+ nodesBySnapshotId.set(snapshot.snapshotId, node);
526
+ } catch (error) {
527
+ hadRestoreFailures = true;
528
+ this.logSnapshotRestoreWarning("Failed to create warm snapshot node; discarding warm dependency state", {
529
+ phase: "create-node",
530
+ snapshotId: snapshot.snapshotId,
531
+ kind: snapshot.kind,
532
+ key: snapshot.key,
533
+ error: error instanceof Error ? { name: error.name, message: error.message } : { message: String(error) }
534
+ });
535
+ }
536
+ }
537
+ if (hadRestoreFailures) {
538
+ this.clearEvaluationCache();
539
+ return;
485
540
  }
486
541
  const resolveNodeSnapshotId = (snapshotId) => nodesBySnapshotId.get(snapshotId);
487
542
  const resolveRequiredNodeSnapshotId = (snapshotId) => {
@@ -492,54 +547,71 @@ class DependencyManager {
492
547
  return node;
493
548
  };
494
549
  for (const snapshot of snapshots.dependency.nodes) {
495
- const dependencies = new Set(snapshot.dependencies.map(resolveNodeSnapshotId).filter((node2) => node2 !== undefined));
496
- if (snapshot.kind === "cell-value") {
497
- const node2 = nodesBySnapshotId.get(snapshot.snapshotId);
498
- node2.restoreResolvedSnapshot({
499
- dependencies,
500
- evaluationResult: evaluationManager.deserializeSingleEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
501
- });
502
- if (snapshot.spillMetaSnapshotId) {
503
- const spillMetaNode = resolveNodeSnapshotId(snapshot.spillMetaSnapshotId);
504
- if (spillMetaNode instanceof import_spill_meta_node.SpillMetaNode) {
505
- node2.setSpillMetaNode(spillMetaNode);
506
- }
507
- }
508
- continue;
509
- }
510
- if (snapshot.kind === "spill-meta") {
511
- const node2 = nodesBySnapshotId.get(snapshot.snapshotId);
512
- node2.restoreResolvedSnapshot({
513
- dependencies,
514
- evaluationResult: evaluationManager.deserializeSpillMetaEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
515
- });
550
+ const targetNode = nodesBySnapshotId.get(snapshot.snapshotId);
551
+ if (!targetNode) {
552
+ hadRestoreFailures = true;
516
553
  continue;
517
554
  }
518
- if (snapshot.kind === "empty") {
519
- const node2 = nodesBySnapshotId.get(snapshot.snapshotId);
520
- node2.restoreResolvedSnapshot({
555
+ const dependencies = new Set(snapshot.dependencies.map(resolveNodeSnapshotId).filter((node) => node !== undefined));
556
+ try {
557
+ if (snapshot.kind === "cell-value") {
558
+ const node2 = targetNode;
559
+ node2.restoreResolvedSnapshot({
560
+ dependencies,
561
+ evaluationResult: evaluationManager.deserializeSingleEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
562
+ });
563
+ if (snapshot.spillMetaSnapshotId) {
564
+ const spillMetaNode = resolveNodeSnapshotId(snapshot.spillMetaSnapshotId);
565
+ if (spillMetaNode instanceof import_spill_meta_node.SpillMetaNode) {
566
+ node2.setSpillMetaNode(spillMetaNode);
567
+ }
568
+ }
569
+ continue;
570
+ }
571
+ if (snapshot.kind === "spill-meta") {
572
+ const node2 = targetNode;
573
+ node2.restoreResolvedSnapshot({
574
+ dependencies,
575
+ evaluationResult: evaluationManager.deserializeSpillMetaEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
576
+ });
577
+ continue;
578
+ }
579
+ if (snapshot.kind === "empty") {
580
+ const node2 = targetNode;
581
+ node2.restoreResolvedSnapshot({
582
+ dependencies,
583
+ evaluationResult: evaluationManager.deserializeSingleEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
584
+ });
585
+ continue;
586
+ }
587
+ if (snapshot.kind === "range") {
588
+ const node2 = targetNode;
589
+ node2.restoreResolvedSnapshot({
590
+ dependencies,
591
+ result: evaluationManager.deserializeEvaluateAllCellsResultSnapshot(snapshot.result, resolveRequiredNodeSnapshotId)
592
+ });
593
+ continue;
594
+ }
595
+ if (snapshot.kind === "resource") {
596
+ continue;
597
+ }
598
+ const node = targetNode;
599
+ node.restoreResolvedSnapshot({
521
600
  dependencies,
522
- evaluationResult: evaluationManager.deserializeSingleEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
601
+ evaluationResult: evaluationManager.deserializeFunctionEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
523
602
  });
524
- continue;
525
- }
526
- if (snapshot.kind === "range") {
527
- const node2 = nodesBySnapshotId.get(snapshot.snapshotId);
528
- node2.restoreResolvedSnapshot({
529
- dependencies,
530
- result: evaluationManager.deserializeEvaluateAllCellsResultSnapshot(snapshot.result, resolveRequiredNodeSnapshotId)
603
+ this.saveAstNode(node, snapshot.contextDependency);
604
+ } catch (error) {
605
+ hadRestoreFailures = true;
606
+ this.resetRestoredNodeToColdState(targetNode);
607
+ this.logSnapshotRestoreWarning("Failed to deserialize warm snapshot node; discarding warm dependency state", {
608
+ phase: "restore-node",
609
+ snapshotId: snapshot.snapshotId,
610
+ kind: snapshot.kind,
611
+ key: snapshot.key,
612
+ error: error instanceof Error ? { name: error.name, message: error.message } : { message: String(error) }
531
613
  });
532
- continue;
533
614
  }
534
- if (snapshot.kind === "resource") {
535
- continue;
536
- }
537
- const node = nodesBySnapshotId.get(snapshot.snapshotId);
538
- node.restoreResolvedSnapshot({
539
- dependencies,
540
- evaluationResult: evaluationManager.deserializeFunctionEvaluationResultSnapshot(snapshot.evaluationResult, resolveRequiredNodeSnapshotId)
541
- });
542
- this.saveAstNode(node, snapshot.contextDependency);
543
615
  }
544
616
  this._spilledValues = new Map(snapshots.dependency.spilledValues);
545
617
  this.rebuildRuntimeIndexes();
@@ -547,20 +619,32 @@ class DependencyManager {
547
619
  }
548
620
  serializeNodeSnapshot(node, evaluationManager, getNodeSnapshotId, allNodeSnapshotIds) {
549
621
  const snapshotId = getNodeSnapshotId(node);
622
+ const getKnownSnapshotId = (dependency) => {
623
+ const directSnapshotId = allNodeSnapshotIds.get(dependency);
624
+ if (directSnapshotId) {
625
+ return directSnapshotId;
626
+ }
627
+ const logicalSnapshotId = this.getLogicalNodeSnapshotId(dependency);
628
+ return allNodeSnapshotIds.values().some((knownSnapshotId) => knownSnapshotId === logicalSnapshotId) ? logicalSnapshotId : undefined;
629
+ };
550
630
  const dependencies = [];
551
631
  for (const dependency of node.getDependencies()) {
552
- const dependencySnapshotId = allNodeSnapshotIds.get(dependency);
632
+ const dependencySnapshotId = getKnownSnapshotId(dependency);
553
633
  if (!dependencySnapshotId) {
554
634
  return;
555
635
  }
556
636
  dependencies.push(dependencySnapshotId);
557
637
  }
638
+ const getReferencedNodeSnapshotId = (dependency) => getNodeSnapshotId(dependency, {
639
+ sourceNode: node,
640
+ relation: "evaluation result errAddress"
641
+ });
558
642
  if (node instanceof import_cell_value_node.CellValueNode) {
559
- const spillMetaSnapshotId = node.spillMeta ? allNodeSnapshotIds.get(node.spillMeta) : undefined;
643
+ const spillMetaSnapshotId = node.spillMeta ? getKnownSnapshotId(node.spillMeta) : undefined;
560
644
  if (node.spillMeta && !spillMetaSnapshotId) {
561
645
  return;
562
646
  }
563
- const evaluationResult2 = evaluationManager.serializeSingleEvaluationResultSnapshot(node.evaluationResult, getNodeSnapshotId);
647
+ const evaluationResult2 = evaluationManager.serializeSingleEvaluationResultSnapshot(node.evaluationResult, getReferencedNodeSnapshotId);
564
648
  if (!evaluationResult2) {
565
649
  return;
566
650
  }
@@ -576,7 +660,7 @@ class DependencyManager {
576
660
  if (node instanceof import_spill_meta_node.SpillMetaNode) {
577
661
  const evaluationResult2 = evaluationManager.serializeSpillMetaEvaluationResultSnapshot(node.evaluationResult, {
578
662
  sourceNode: node,
579
- getNodeSnapshotId
663
+ getNodeSnapshotId: getReferencedNodeSnapshotId
580
664
  });
581
665
  if (!evaluationResult2) {
582
666
  return;
@@ -590,7 +674,7 @@ class DependencyManager {
590
674
  };
591
675
  }
592
676
  if (node instanceof import_empty_cell_evaluation_node.EmptyCellEvaluationNode) {
593
- const evaluationResult2 = evaluationManager.serializeSingleEvaluationResultSnapshot(node.evaluationResult, getNodeSnapshotId);
677
+ const evaluationResult2 = evaluationManager.serializeSingleEvaluationResultSnapshot(node.evaluationResult, getReferencedNodeSnapshotId);
594
678
  if (!evaluationResult2) {
595
679
  return;
596
680
  }
@@ -603,7 +687,7 @@ class DependencyManager {
603
687
  };
604
688
  }
605
689
  if (node instanceof import_range_evaluation_node.RangeEvaluationNode) {
606
- const result = evaluationManager.serializeEvaluateAllCellsResultSnapshot(node.result, getNodeSnapshotId);
690
+ const result = evaluationManager.serializeEvaluateAllCellsResultSnapshot(node.result, getReferencedNodeSnapshotId);
607
691
  if (!result) {
608
692
  return;
609
693
  }
@@ -625,7 +709,7 @@ class DependencyManager {
625
709
  }
626
710
  const evaluationResult = evaluationManager.serializeFunctionEvaluationResultSnapshot(node.evaluationResult, {
627
711
  sourceNode: node,
628
- getNodeSnapshotId
712
+ getNodeSnapshotId: getReferencedNodeSnapshotId
629
713
  });
630
714
  if (!evaluationResult) {
631
715
  return;
@@ -1451,4 +1535,4 @@ class DependencyManager {
1451
1535
  }
1452
1536
  }
1453
1537
 
1454
- //# debugId=1436FDFA1813AF4B64756E2164756E21
1538
+ //# debugId=1B8CBFB24400CA2564756E2164756E21