@univerjs-pro/engine-formula-rust 1.0.0 → 1.0.2

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/lib/cjs/index.cjs CHANGED
@@ -32,6 +32,7 @@ __export(index_exports, {
32
32
  RUST_UPSERT_REFERENCE_DATA_MUTATION_ID: () => RUST_UPSERT_REFERENCE_DATA_MUTATION_ID,
33
33
  RustCalculateFormulaService: () => RustCalculateFormulaService,
34
34
  RustEngineSyncController: () => RustEngineSyncController,
35
+ RustFormulaEngineSession: () => RustFormulaEngineSession,
35
36
  RustFormulaProjectionService: () => RustFormulaProjectionService,
36
37
  UniverRustFormulaEnginePlugin: () => UniverRustFormulaEnginePlugin,
37
38
  analyzeNumberFormatBatch: () => analyzeNumberFormatBatch,
@@ -150,11 +151,6 @@ function loadSnapshotOnRust(snapshotJson) {
150
151
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
151
152
  return nativeBinding.rustEngineLoadSnapshot(snapshotJson);
152
153
  }
153
- function loadSnapshotBinaryOnRust(snapshotBytes) {
154
- if (!nativeBinding)
155
- throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
156
- return nativeBinding.rustEngineLoadSnapshotBinary(snapshotBytes);
157
- }
158
154
  function applyMutationOnRust(mutationJson) {
159
155
  if (!nativeBinding)
160
156
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
@@ -205,11 +201,6 @@ function syncRustFormulaDependenciesOnRust(inputJson) {
205
201
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
206
202
  return nativeBinding.rustEngineSyncFormulaDependencies(inputJson);
207
203
  }
208
- function inspectRustFormulaDependencyGraphOnRust() {
209
- if (!nativeBinding)
210
- throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
211
- return nativeBinding.rustEngineInspectFormulaDependencyGraph();
212
- }
213
204
  function markRustFormulaDirtyOnRust(inputJson) {
214
205
  if (!nativeBinding)
215
206
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
@@ -225,21 +216,34 @@ function clearRustFormulaDirtyOnRust() {
225
216
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
226
217
  return nativeBinding.rustEngineClearFormulaDirty();
227
218
  }
228
- function executeDirtyFormulasOnRust(maxIteration, includeCalculatedNodes, includeRuntimeData, includeResultBatches) {
229
- if (!nativeBinding)
230
- throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
231
- return nativeBinding.rustEngineExecuteDirtyFormulas(
232
- maxIteration,
233
- includeCalculatedNodes,
234
- includeRuntimeData,
235
- includeResultBatches
236
- );
237
- }
238
219
  function materializeWorkbookSnapshotOnRust(workbookJson, unitId, rev, dirtyInputJson) {
239
220
  if (!nativeBinding)
240
221
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
241
222
  return nativeBinding.rustMaterializeWorkbookSnapshot(workbookJson, unitId, rev, dirtyInputJson);
242
223
  }
224
+ var RustFormulaEngineSession = class {
225
+ _engine = null;
226
+ _disposed = !1;
227
+ async initialize() {
228
+ if (this._disposed) throw new Error("Rust formula engine session is disposed");
229
+ if (this._engine) return;
230
+ let binding = await loadNativeBinding();
231
+ if (this._disposed) throw new Error("Rust formula engine session is disposed");
232
+ if (!this._engine) {
233
+ if (typeof binding.RustFormulaEngine != "function")
234
+ throw new Error("Native formula binding lacks instance isolation; upgrade engine-formula-rust-binding");
235
+ this._engine = new binding.RustFormulaEngine();
236
+ }
237
+ }
238
+ get binding() {
239
+ if (this._disposed) throw new Error("Rust formula engine session is disposed");
240
+ if (!this._engine) throw new Error("Rust formula engine session is not initialized");
241
+ return this._engine;
242
+ }
243
+ dispose() {
244
+ this._disposed || (this._disposed = !0, this._engine?.dispose(), this._engine = null);
245
+ }
246
+ };
243
247
 
244
248
  // src/controllers/rust-engine-sync.controller.ts
245
249
  var import_core2 = require("@univerjs/core");
@@ -437,12 +441,20 @@ function createFormulaProjectionDesyncSignal(reason, error, mutationId) {
437
441
  };
438
442
  }
439
443
  var RustFormulaProjectionService = class {
444
+ engine = new RustFormulaEngineSession();
445
+ dispose() {
446
+ this.engine.dispose();
447
+ }
440
448
  _nativeLoaded = !1;
441
449
  async load(workbooks) {
442
450
  await this._ensureNativeLoaded();
443
451
  try {
444
452
  return {
445
- stats: JSON.parse(loadSnapshotOnRust(JSON.stringify(serializeRuntimeWorkbookSnapshots(workbooks))))
453
+ stats: JSON.parse(
454
+ this.engine.binding.rustEngineLoadSnapshot(
455
+ JSON.stringify(serializeRuntimeWorkbookSnapshots(workbooks))
456
+ )
457
+ )
446
458
  };
447
459
  } catch (error) {
448
460
  return {
@@ -455,7 +467,9 @@ var RustFormulaProjectionService = class {
455
467
  await this._ensureNativeLoaded();
456
468
  try {
457
469
  return {
458
- stats: JSON.parse(applyMutationOnRust(JSON.stringify(normalizeRustEngineMutation(mutation)))),
470
+ stats: JSON.parse(
471
+ this.engine.binding.rustEngineApplyMutation(JSON.stringify(normalizeRustEngineMutation(mutation)))
472
+ ),
459
473
  dependencyInvalidated: !isRustIncrementalDependencyMutation(mutation.id)
460
474
  };
461
475
  } catch (error) {
@@ -467,16 +481,16 @@ var RustFormulaProjectionService = class {
467
481
  }
468
482
  }
469
483
  async syncFormulaDependencies(input) {
470
- return await this._ensureNativeLoaded(), JSON.parse(syncRustFormulaDependenciesOnRust(JSON.stringify(input)));
484
+ return await this._ensureNativeLoaded(), JSON.parse(this.engine.binding.rustEngineSyncFormulaDependencies(JSON.stringify(input)));
471
485
  }
472
486
  async markDirty(input) {
473
- return await this._ensureNativeLoaded(), JSON.parse(markRustFormulaDirtyOnRust(JSON.stringify(input)));
487
+ return await this._ensureNativeLoaded(), JSON.parse(this.engine.binding.rustEngineMarkFormulaDirty(JSON.stringify(input)));
474
488
  }
475
489
  async calculateDirty(maxIteration = 1) {
476
490
  await this._ensureNativeLoaded();
477
491
  try {
478
492
  let output = JSON.parse(
479
- executeDirtyFormulasOnRust(maxIteration, !1, !1, !0)
493
+ this.engine.binding.rustEngineExecuteDirtyFormulas(maxIteration, !1, !1, !0)
480
494
  );
481
495
  return rustExecutionOutputToFormulaCalculationPatch(output);
482
496
  } catch (error) {
@@ -491,7 +505,7 @@ var RustFormulaProjectionService = class {
491
505
  async reset() {
492
506
  await this._ensureNativeLoaded();
493
507
  try {
494
- return clearRustFormulaDirtyOnRust(), clearRustFormulaDependenciesOnRust(
508
+ return this.engine.binding.rustEngineClearFormulaDirty(), this.engine.binding.rustEngineClearFormulaDependencies(
495
509
  JSON.stringify({
496
510
  unitId: "",
497
511
  clearSheetFormulas: !0,
@@ -499,7 +513,11 @@ var RustFormulaProjectionService = class {
499
513
  clearOtherFormulas: !0
500
514
  })
501
515
  ), {
502
- stats: JSON.parse(loadSnapshotOnRust(JSON.stringify({ workbooks: [] })))
516
+ stats: JSON.parse(
517
+ this.engine.binding.rustEngineLoadSnapshot(
518
+ JSON.stringify({ workbooks: [] })
519
+ )
520
+ )
503
521
  };
504
522
  } catch (error) {
505
523
  return {
@@ -511,7 +529,7 @@ var RustFormulaProjectionService = class {
511
529
  async disposeWorkbook(unitId) {
512
530
  await this._ensureNativeLoaded();
513
531
  try {
514
- return { stats: JSON.parse(disposeWorkbookOnRust(unitId)) };
532
+ return { stats: JSON.parse(this.engine.binding.rustEngineDisposeWorkbook(unitId)) };
515
533
  } catch (error) {
516
534
  return {
517
535
  desync: createFormulaProjectionDesyncSignal("workbook-dispose-failed", error),
@@ -520,7 +538,7 @@ var RustFormulaProjectionService = class {
520
538
  }
521
539
  }
522
540
  async _ensureNativeLoaded() {
523
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0);
541
+ this._nativeLoaded || (await this.engine.initialize(), this._nativeLoaded = !0);
524
542
  }
525
543
  };
526
544
  function normalizeRustEngineMutation(mutation) {
@@ -1054,19 +1072,6 @@ function isRecord(value) {
1054
1072
  }
1055
1073
 
1056
1074
  // src/controllers/rust-engine-sync.controller.ts
1057
- var rustEngineSyncState = {
1058
- snapshotEpoch: 0,
1059
- dependencyInvalidationEpoch: 0
1060
- };
1061
- function getRustEngineSyncState() {
1062
- return { ...rustEngineSyncState };
1063
- }
1064
- function markRustSnapshotLoaded() {
1065
- rustEngineSyncState.snapshotEpoch += 1, rustEngineSyncState.dependencyInvalidationEpoch += 1;
1066
- }
1067
- function markRustFormulaDependenciesInvalidated() {
1068
- rustEngineSyncState.dependencyInvalidationEpoch += 1;
1069
- }
1070
1075
  function emitRustEngineSyncDebugEvent(event) {
1071
1076
  let hook = globalThis.__UNIVER_RUST_FORMULA_DEBUG_HOOK__;
1072
1077
  typeof hook == "function" && hook(event);
@@ -1106,6 +1111,17 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1106
1111
  this._initialize();
1107
1112
  }
1108
1113
  _commandService;
1114
+ engine = new RustFormulaEngineSession();
1115
+ _syncState = { snapshotEpoch: 0, dependencyInvalidationEpoch: 0 };
1116
+ getSyncState() {
1117
+ return { ...this._syncState };
1118
+ }
1119
+ _markSnapshotLoaded() {
1120
+ this._syncState.snapshotEpoch += 1, this._syncState.dependencyInvalidationEpoch += 1;
1121
+ }
1122
+ _markDependenciesInvalidated() {
1123
+ this._syncState.dependencyInvalidationEpoch += 1;
1124
+ }
1109
1125
  _nativeReady = !1;
1110
1126
  _snapshotLoaded = !1;
1111
1127
  _projectionLoadPromise = null;
@@ -1139,7 +1155,7 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1139
1155
  this._projectionDeltaBarrier = barrier;
1140
1156
  }
1141
1157
  async _loadProjection(workbooks) {
1142
- await loadNativeBinding(), this._nativeReady = !0;
1158
+ await this.engine.initialize(), this._nativeReady = !0;
1143
1159
  let serializeStartedAt = performance.now(), snapshot = serializeRuntimeWorkbookSnapshots(workbooks);
1144
1160
  this._loadSerializedSnapshot(snapshot, performance.now() - serializeStartedAt);
1145
1161
  }
@@ -1162,20 +1178,17 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1162
1178
  disposeProjectionWorkbook(unitId) {
1163
1179
  if (!(!this._nativeReady || !this._snapshotLoaded))
1164
1180
  try {
1165
- disposeWorkbookOnRust(unitId), markRustFormulaDependenciesInvalidated();
1181
+ this.engine.binding.rustEngineDisposeWorkbook(unitId), this._markDependenciesInvalidated();
1166
1182
  } catch {
1167
- this._markProjectionDesynced();
1183
+ this.markProjectionDesynced();
1168
1184
  }
1169
1185
  }
1170
1186
  dispose() {
1171
- if (super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, this._projectionDeltaBarrier = Promise.resolve(), !this._nativeReady) {
1172
- this._snapshotLoaded = !1;
1173
- return;
1174
- }
1187
+ super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, this._projectionDeltaBarrier = Promise.resolve();
1175
1188
  try {
1176
- disposeAllWorkbooksOnRust();
1189
+ this.engine.dispose();
1177
1190
  } catch {
1178
- this._markProjectionDesynced();
1191
+ this.markProjectionDesynced();
1179
1192
  return;
1180
1193
  }
1181
1194
  this._nativeReady = !1, this._snapshotLoaded = !1;
@@ -1183,7 +1196,7 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1183
1196
  _loadSerializedSnapshot(snapshot, serializeMs) {
1184
1197
  let precisionAsDisplayedWorkbookCount = snapshot.workbooks.filter(
1185
1198
  (workbook) => workbook.calculation?.fullPrecision === !1
1186
- ).length, displayPrecisionCellCount = countDisplayPrecisionCells(snapshot), pendingCountCoveredBySnapshot = this._pendingMutations.length, stringifyStartedAt = performance.now(), snapshotJson = JSON.stringify(snapshot), stringifyMs = performance.now() - stringifyStartedAt, snapshotBuffer = globalThis.Buffer?.from(snapshotJson), nativeStartedAt = performance.now(), nativeOutput = snapshotBuffer ? loadSnapshotBinaryOnRust(snapshotBuffer) : loadSnapshotOnRust(snapshotJson), nativeMs = performance.now() - nativeStartedAt, nativeTimings;
1199
+ ).length, displayPrecisionCellCount = countDisplayPrecisionCells(snapshot), pendingCountCoveredBySnapshot = this._pendingMutations.length, stringifyStartedAt = performance.now(), snapshotJson = JSON.stringify(snapshot), stringifyMs = performance.now() - stringifyStartedAt, snapshotBuffer = globalThis.Buffer?.from(snapshotJson), nativeStartedAt = performance.now(), nativeOutput = snapshotBuffer ? this.engine.binding.rustEngineLoadSnapshotBinary(snapshotBuffer) : this.engine.binding.rustEngineLoadSnapshot(snapshotJson), nativeMs = performance.now() - nativeStartedAt, nativeTimings;
1187
1200
  try {
1188
1201
  nativeTimings = JSON.parse(nativeOutput).timingsMs;
1189
1202
  } catch {
@@ -1202,7 +1215,7 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1202
1215
  transport: snapshotBuffer ? "binary-json" : "string-json",
1203
1216
  nativeTimings
1204
1217
  }
1205
- }), this._pendingMutations.splice(0, pendingCountCoveredBySnapshot), this._snapshotLoaded = !0, markRustSnapshotLoaded(), this._flushPendingMutations();
1218
+ }), this._pendingMutations.splice(0, pendingCountCoveredBySnapshot), this._snapshotLoaded = !0, this._markSnapshotLoaded(), this._flushPendingMutations();
1206
1219
  }
1207
1220
  _queueOrSyncMutation(mutation) {
1208
1221
  if (!this._nativeReady || !this._snapshotLoaded) {
@@ -1220,9 +1233,9 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1220
1233
  _syncMutation(mutation) {
1221
1234
  let totalStartedAt = performance.now(), stringifyStartedAt = performance.now(), payload = JSON.stringify(normalizeRustEngineMutation(mutation)), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now();
1222
1235
  try {
1223
- applyMutationOnRust(payload), isRustIncrementalDependencyMutation(mutation.id) || markRustFormulaDependenciesInvalidated();
1236
+ this.engine.binding.rustEngineApplyMutation(payload), isRustIncrementalDependencyMutation(mutation.id) || this._markDependenciesInvalidated();
1224
1237
  } catch {
1225
- this._markProjectionDesynced();
1238
+ this.markProjectionDesynced();
1226
1239
  } finally {
1227
1240
  emitRustEngineSyncDebugEvent({
1228
1241
  type: "applyMutation",
@@ -1238,7 +1251,11 @@ var RustEngineSyncController = class extends import_core2.Disposable {
1238
1251
  });
1239
1252
  }
1240
1253
  }
1241
- _markProjectionDesynced() {
1254
+ /**
1255
+ * Marks the native projection as out of sync so the next mutation reloads it.
1256
+ * Also used by the projection controller when a background projection load fails.
1257
+ */
1258
+ markProjectionDesynced() {
1242
1259
  this._nativeReady = !1, this._snapshotLoaded = !1;
1243
1260
  }
1244
1261
  _shouldSyncMutation(command, options) {
@@ -1302,7 +1319,7 @@ async function analyzeNumberFormatBatch(input) {
1302
1319
  var import_core5 = require("@univerjs/core"), import_engine_formula4 = require("@univerjs/engine-formula"), import_engine_formula5 = require("@univerjs-pro/engine-formula");
1303
1320
 
1304
1321
  // package.json
1305
- var name = "@univerjs-pro/engine-formula-rust", version = "1.0.0";
1322
+ var name = "@univerjs-pro/engine-formula-rust", version = "1.0.2";
1306
1323
 
1307
1324
  // src/controllers/rust-same-runtime-projection.controller.ts
1308
1325
  var import_core3 = require("@univerjs/core"), import_engine_formula = require("@univerjs/engine-formula");
@@ -1331,7 +1348,9 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
1331
1348
  import_core3.UniverInstanceType.UNIVER_BASE
1332
1349
  ))
1333
1350
  this._rustEngineSyncController.setProjectionManagedTableUnit(base.getUnitId()), this._rememberBaseProjectionStructure(base.getSnapshot());
1334
- this._initialProjectionLoad = this._loadAllWorkbookProjections(), this.disposeWithMe(
1351
+ this._initialProjectionLoad = this._loadAllWorkbookProjections().catch(() => {
1352
+ this._rustEngineSyncController.markProjectionDesynced();
1353
+ }), this.disposeWithMe(
1335
1354
  (0, import_core3.toDisposable)(
1336
1355
  this._univerInstanceService.getTypeOfUnitAdded$(import_core3.UniverInstanceType.UNIVER_SHEET).subscribe(({ unit }) => {
1337
1356
  this._enqueueProjectionDelta(() => {
@@ -1926,14 +1945,19 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
1926
1945
  this._runtimeService.setRuntimeFeatureRange(featureId, featureRange);
1927
1946
  }
1928
1947
  async execute(formulaDatasetConfig) {
1929
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), await this._rustEngineSyncController.waitForProjectionLoad(), this._externalFormulaDatasetConfig = formulaDatasetConfig, this._currentConfigService.load(formulaDatasetConfig), this._externalRequestGeneration++, this._externalInflight.clear(), this._externalCompleted.clear(), this._runtimeService.setFormulaExecuteStage(import_engine_formula2.FormulaExecuteStageType.START), this._executionInProgressListener$.next(this._runtimeService.getRuntimeState()), this._runtimeService.reset();
1948
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), await this._rustEngineSyncController.waitForProjectionLoad(), this._externalFormulaDatasetConfig = formulaDatasetConfig, this._currentConfigService.load(formulaDatasetConfig), this._externalRequestGeneration++, this._externalInflight.clear(), this._externalCompleted.clear(), this._runtimeService.setFormulaExecuteStage(import_engine_formula2.FormulaExecuteStageType.START), this._executionInProgressListener$.next(this._runtimeService.getRuntimeState()), this._runtimeService.reset();
1930
1949
  let cycleReferenceCount = Math.max(formulaDatasetConfig.maxIteration || 1, 1);
1931
1950
  await this._executeLock.acquire("FORMULA_EXECUTION_LOCK", async () => {
1932
1951
  this._runtimeService.setFormulaCycleIndex(0), await this._executeStep(cycleReferenceCount) > 0 ? this._runtimeService.markedAsSuccessfullyExecuted() : this._runtimeService.markedAsNoFunctionsExecuted(), this._runtimeService.setFormulaExecuteStage(import_engine_formula2.FormulaExecuteStageType.CALCULATION_COMPLETED), this._executionInProgressListener$.next(this._runtimeService.getRuntimeState()), this._executionCompleteListener$.next(this._runtimeService.getAllRuntimeData()), this._runtimeService.reset();
1933
1952
  });
1934
1953
  }
1935
1954
  async _executeStep(maxIteration) {
1936
- let syncedFeatures = this._syncRustFormulaDependencies(void 0, !0), previousFeatureSignatures = this._featureSignatureMap(syncedFeatures), executeStartedAt = performance.now(), outputJson = executeDirtyFormulasOnRust(maxIteration, !1, !1, !0), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount = output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt;
1955
+ let syncedFeatures = this._syncRustFormulaDependencies(void 0, !0), previousFeatureSignatures = this._featureSignatureMap(syncedFeatures), executeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineExecuteDirtyFormulas(
1956
+ maxIteration,
1957
+ !1,
1958
+ !1,
1959
+ !0
1960
+ ), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount = output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt;
1937
1961
  output = await this._resolveExternalReferenceNeeds(output, maxIteration);
1938
1962
  let applyStartedAt = performance.now(), applyBreakdown = await this._applyRustDependencyOutput(output), applyMs = performance.now() - applyStartedAt;
1939
1963
  if (emitRustFormulaDebugEvent({
@@ -1969,7 +1993,12 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
1969
1993
  this._markRustFormulaDirty(
1970
1994
  this._currentConfigService.getDirtyData(),
1971
1995
  this._dirtyFeatureMapFor(changedFeatures)
1972
- ), executeStartedAt = performance.now(), outputJson = executeDirtyFormulasOnRust(maxIteration, !1, !1, !0), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount += output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt, output = await this._resolveExternalReferenceNeeds(output, maxIteration), applyStartedAt = performance.now(), applyBreakdown = await this._applyRustDependencyOutput(output), applyMs = performance.now() - applyStartedAt, emitRustFormulaDebugEvent({
1996
+ ), executeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineExecuteDirtyFormulas(
1997
+ maxIteration,
1998
+ !1,
1999
+ !1,
2000
+ !0
2001
+ ), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount += output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt, output = await this._resolveExternalReferenceNeeds(output, maxIteration), applyStartedAt = performance.now(), applyBreakdown = await this._applyRustDependencyOutput(output), applyMs = performance.now() - applyStartedAt, emitRustFormulaDebugEvent({
1973
2002
  type: "executeDirtyFormulas",
1974
2003
  payload: {
1975
2004
  calculatedNodeCount: output.calculatedNodeCount,
@@ -2014,7 +2043,14 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2014
2043
  loadedRanges,
2015
2044
  this._superTableService
2016
2045
  ) === 0) break;
2017
- this._syncRustFormulaDependencies(), output = JSON.parse(executeDirtyFormulasOnRust(maxIteration, !1, !1, !0));
2046
+ this._syncRustFormulaDependencies(), output = JSON.parse(
2047
+ this._rustEngineSyncController.engine.binding.rustEngineExecuteDirtyFormulas(
2048
+ maxIteration,
2049
+ !1,
2050
+ !1,
2051
+ !0
2052
+ )
2053
+ );
2018
2054
  }
2019
2055
  return output;
2020
2056
  }
@@ -2188,7 +2224,7 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2188
2224
  };
2189
2225
  }
2190
2226
  _syncRustFormulaDependencies(dirtyUnitFeatureMapOverride, includeExternalReferences = !1) {
2191
- let syncState = getRustEngineSyncState(), externalReferences = includeExternalReferences ? this._externalFormulaDatasetConfig?.externalReferences ?? {} : void 0, externalReferenceSignature = externalReferences ? JSON.stringify(externalReferences) : this._syncedExternalReferenceSignature, shouldSendExternalReferences = includeExternalReferences && (externalReferenceSignature !== "{}" || this._syncedExternalReferenceSignature !== "{}"), rebuildSheetFormulas = this._syncedSnapshotEpoch !== syncState.snapshotEpoch || this._syncedDependencyInvalidationEpoch !== syncState.dependencyInvalidationEpoch || shouldSendExternalReferences, collectStartedAt = performance.now(), state = this._collectRustFormulaDependencySyncState(), collectMs = performance.now() - collectStartedAt;
2227
+ let syncState = this._rustEngineSyncController.getSyncState(), externalReferences = includeExternalReferences ? this._externalFormulaDatasetConfig?.externalReferences ?? {} : void 0, externalReferenceSignature = externalReferences ? JSON.stringify(externalReferences) : this._syncedExternalReferenceSignature, shouldSendExternalReferences = includeExternalReferences && (externalReferenceSignature !== "{}" || this._syncedExternalReferenceSignature !== "{}"), rebuildSheetFormulas = this._syncedSnapshotEpoch !== syncState.snapshotEpoch || this._syncedDependencyInvalidationEpoch !== syncState.dependencyInvalidationEpoch || shouldSendExternalReferences, collectStartedAt = performance.now(), state = this._collectRustFormulaDependencySyncState(), collectMs = performance.now() - collectStartedAt;
2192
2228
  if (!(shouldSendExternalReferences || rebuildSheetFormulas || state.featureCalculations.length > 0 || state.otherFormulas.length > 0))
2193
2229
  return emitRustFormulaDebugEvent({
2194
2230
  type: "syncDependencies",
@@ -2212,7 +2248,7 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2212
2248
  featureCalculations: state.featureCalculations,
2213
2249
  otherFormulas: state.otherFormulas,
2214
2250
  ...shouldSendExternalReferences ? { externalReferences } : {}
2215
- }), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = syncRustFormulaDependenciesOnRust(inputJson), nativeMs = performance.now() - nativeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), parseMs = performance.now() - parseStartedAt;
2251
+ }), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineSyncFormulaDependencies(inputJson), nativeMs = performance.now() - nativeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), parseMs = performance.now() - parseStartedAt;
2216
2252
  return emitRustFormulaDebugEvent({
2217
2253
  type: "syncDependencies",
2218
2254
  payload: {
@@ -2234,7 +2270,7 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2234
2270
  }
2235
2271
  _syncRustFormulaDependencyDefinitions() {
2236
2272
  let state = this._collectRustFormulaDependencySyncState();
2237
- return syncRustFormulaDependenciesOnRust(
2273
+ return this._rustEngineSyncController.engine.binding.rustEngineSyncFormulaDependencies(
2238
2274
  JSON.stringify({
2239
2275
  rebuildSheetFormulas: !1,
2240
2276
  featureCalculations: state.featureCalculations,
@@ -2309,7 +2345,7 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2309
2345
  dirtyUnitOtherFormulaMap: dirtyData.dirtyUnitOtherFormulaMap,
2310
2346
  dirtyNameMap: dirtyData.dirtyNameMap,
2311
2347
  dirtyDefinedNameMap: dirtyData.dirtyDefinedNameMap
2312
- }, stringifyStartedAt = performance.now(), inputJson = JSON.stringify(payload), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = markRustFormulaDirtyOnRust(inputJson), nativeMs = performance.now() - nativeStartedAt, rustTimings;
2348
+ }, stringifyStartedAt = performance.now(), inputJson = JSON.stringify(payload), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineMarkFormulaDirty(inputJson), nativeMs = performance.now() - nativeStartedAt, rustTimings;
2313
2349
  try {
2314
2350
  rustTimings = JSON.parse(outputJson).timings;
2315
2351
  } catch {
@@ -2491,7 +2527,7 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2491
2527
  });
2492
2528
  }
2493
2529
  async calculate(formulaString) {
2494
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0);
2530
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0);
2495
2531
  let unitId = "__rust_formula_calculate__", sheetId = "__sheet__", input = {
2496
2532
  config: { maxIteration: 1, intervalCount: DEFAULT_INTERVAL_COUNT },
2497
2533
  formulaData: {
@@ -2516,7 +2552,7 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2516
2552
  return JSON.parse(executeOnRust(JSON.stringify(input))).runtimeData?.[unitId]?.[sheetId]?.[0]?.[0] ?? null;
2517
2553
  }
2518
2554
  async executeFormulas(formulas, rowData) {
2519
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._currentConfigService.loadDataLite(rowData);
2555
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._currentConfigService.loadDataLite(rowData);
2520
2556
  let unitData = this._currentConfigService.getUnitData(), definedNames = {};
2521
2557
  for (let [unitId, names] of Object.entries(this._definedNamesService.getAllDefinedNames()))
2522
2558
  for (let [id, name2] of Object.entries(names))
@@ -2539,12 +2575,12 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2539
2575
  return this._formulaExecutionOutputToResultMap(formulas, output);
2540
2576
  }
2541
2577
  async getAllDependencyJson(_rowData) {
2542
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2578
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2543
2579
  let graph = this._getRustDependencyGraph(), inspect = this._getRustInspectGraph();
2544
2580
  return this._rustAllDependencyJson(graph, inspect);
2545
2581
  }
2546
2582
  async getCellDependencyJson(unitId, sheetId, row, column, _rowData) {
2547
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2583
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2548
2584
  let graph = this._getRustDependencyGraph(unitId), all = this._rustGraphDependencyJson(graph), current = all.find(
2549
2585
  (item) => item.unitId === unitId && item.subUnitId === sheetId && item.row === row && item.column === column
2550
2586
  );
@@ -2558,16 +2594,18 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2558
2594
  };
2559
2595
  }
2560
2596
  async getRangeDependents(unitRanges) {
2561
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2597
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2562
2598
  let graph = this._getRustDependencyGraph(), graphItems = this._rustGraphDependencyJson(graph), graphByCell = this._rustDependencyJsonByCell(graphItems), dirty = JSON.parse(
2563
- getRustDirtyDependenciesOnRust(JSON.stringify(this._serializeUnitRanges(unitRanges)))
2599
+ this._rustEngineSyncController.engine.binding.rustEngineGetDirtyDependencies(
2600
+ JSON.stringify(this._serializeUnitRanges(unitRanges))
2601
+ )
2564
2602
  );
2565
2603
  return this._uniqueDependencyJson(
2566
2604
  (dirty.direct ?? dirty.affected ?? []).map((cell) => graphByCell.get(this._cellKey(cell))).filter(Boolean)
2567
2605
  );
2568
2606
  }
2569
2607
  async getInRangeFormulas(unitRanges) {
2570
- return this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions(), this._rustGraphDependencyJson(this._getRustDependencyGraph()).filter(
2608
+ return this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions(), this._rustGraphDependencyJson(this._getRustDependencyGraph()).filter(
2571
2609
  (item) => this._cellInUnitRanges(item.unitId, item.subUnitId, item.row, item.column, unitRanges)
2572
2610
  );
2573
2611
  }
@@ -2613,10 +2651,14 @@ var RustCalculateFormulaService = class extends import_core4.Disposable {
2613
2651
  }), result;
2614
2652
  }
2615
2653
  _getRustDependencyGraph(unitId) {
2616
- return JSON.parse(buildRustDependencyGraphOnRust(unitId));
2654
+ return JSON.parse(
2655
+ this._rustEngineSyncController.engine.binding.rustEngineBuildDependencyGraph(unitId)
2656
+ );
2617
2657
  }
2618
2658
  _getRustInspectGraph() {
2619
- return JSON.parse(inspectRustFormulaDependencyGraphOnRust());
2659
+ return JSON.parse(
2660
+ this._rustEngineSyncController.engine.binding.rustEngineInspectFormulaDependencyGraph()
2661
+ );
2620
2662
  }
2621
2663
  _rustAllDependencyJson(graph, inspect) {
2622
2664
  let cellItems = this._rustGraphDependencyJson(graph), seen = new Set(cellItems.map((item) => item.treeId)), nonCellItems = (inspect.nodes ?? []).filter((item) => item.node.nodeType !== "cellFormula" && !seen.has(item.index)).map((item) => this._rustFormulaNodeToDependencyJson(item.index, item.node));
@@ -2823,6 +2865,7 @@ async function materializeWorkbookSnapshot(workbook, unitID, rev, dirtyInput) {
2823
2865
  RUST_UPSERT_REFERENCE_DATA_MUTATION_ID,
2824
2866
  RustCalculateFormulaService,
2825
2867
  RustEngineSyncController,
2868
+ RustFormulaEngineSession,
2826
2869
  RustFormulaProjectionService,
2827
2870
  UniverRustFormulaEnginePlugin,
2828
2871
  analyzeNumberFormatBatch,
package/lib/es/index.js CHANGED
@@ -80,11 +80,6 @@ function loadSnapshotOnRust(snapshotJson) {
80
80
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
81
81
  return nativeBinding.rustEngineLoadSnapshot(snapshotJson);
82
82
  }
83
- function loadSnapshotBinaryOnRust(snapshotBytes) {
84
- if (!nativeBinding)
85
- throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
86
- return nativeBinding.rustEngineLoadSnapshotBinary(snapshotBytes);
87
- }
88
83
  function applyMutationOnRust(mutationJson) {
89
84
  if (!nativeBinding)
90
85
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
@@ -135,11 +130,6 @@ function syncRustFormulaDependenciesOnRust(inputJson) {
135
130
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
136
131
  return nativeBinding.rustEngineSyncFormulaDependencies(inputJson);
137
132
  }
138
- function inspectRustFormulaDependencyGraphOnRust() {
139
- if (!nativeBinding)
140
- throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
141
- return nativeBinding.rustEngineInspectFormulaDependencyGraph();
142
- }
143
133
  function markRustFormulaDirtyOnRust(inputJson) {
144
134
  if (!nativeBinding)
145
135
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
@@ -155,21 +145,34 @@ function clearRustFormulaDirtyOnRust() {
155
145
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
156
146
  return nativeBinding.rustEngineClearFormulaDirty();
157
147
  }
158
- function executeDirtyFormulasOnRust(maxIteration, includeCalculatedNodes, includeRuntimeData, includeResultBatches) {
159
- if (!nativeBinding)
160
- throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
161
- return nativeBinding.rustEngineExecuteDirtyFormulas(
162
- maxIteration,
163
- includeCalculatedNodes,
164
- includeRuntimeData,
165
- includeResultBatches
166
- );
167
- }
168
148
  function materializeWorkbookSnapshotOnRust(workbookJson, unitId, rev, dirtyInputJson) {
169
149
  if (!nativeBinding)
170
150
  throw new Error("Native binding not loaded. Call loadNativeBinding() first.");
171
151
  return nativeBinding.rustMaterializeWorkbookSnapshot(workbookJson, unitId, rev, dirtyInputJson);
172
152
  }
153
+ var RustFormulaEngineSession = class {
154
+ _engine = null;
155
+ _disposed = !1;
156
+ async initialize() {
157
+ if (this._disposed) throw new Error("Rust formula engine session is disposed");
158
+ if (this._engine) return;
159
+ let binding = await loadNativeBinding();
160
+ if (this._disposed) throw new Error("Rust formula engine session is disposed");
161
+ if (!this._engine) {
162
+ if (typeof binding.RustFormulaEngine != "function")
163
+ throw new Error("Native formula binding lacks instance isolation; upgrade engine-formula-rust-binding");
164
+ this._engine = new binding.RustFormulaEngine();
165
+ }
166
+ }
167
+ get binding() {
168
+ if (this._disposed) throw new Error("Rust formula engine session is disposed");
169
+ if (!this._engine) throw new Error("Rust formula engine session is not initialized");
170
+ return this._engine;
171
+ }
172
+ dispose() {
173
+ this._disposed || (this._disposed = !0, this._engine?.dispose(), this._engine = null);
174
+ }
175
+ };
173
176
 
174
177
  // src/controllers/rust-engine-sync.controller.ts
175
178
  import { CommandType, Disposable, ICommandService, setDependencies } from "@univerjs/core";
@@ -372,12 +375,20 @@ function createFormulaProjectionDesyncSignal(reason, error, mutationId) {
372
375
  };
373
376
  }
374
377
  var RustFormulaProjectionService = class {
378
+ engine = new RustFormulaEngineSession();
379
+ dispose() {
380
+ this.engine.dispose();
381
+ }
375
382
  _nativeLoaded = !1;
376
383
  async load(workbooks) {
377
384
  await this._ensureNativeLoaded();
378
385
  try {
379
386
  return {
380
- stats: JSON.parse(loadSnapshotOnRust(JSON.stringify(serializeRuntimeWorkbookSnapshots(workbooks))))
387
+ stats: JSON.parse(
388
+ this.engine.binding.rustEngineLoadSnapshot(
389
+ JSON.stringify(serializeRuntimeWorkbookSnapshots(workbooks))
390
+ )
391
+ )
381
392
  };
382
393
  } catch (error) {
383
394
  return {
@@ -390,7 +401,9 @@ var RustFormulaProjectionService = class {
390
401
  await this._ensureNativeLoaded();
391
402
  try {
392
403
  return {
393
- stats: JSON.parse(applyMutationOnRust(JSON.stringify(normalizeRustEngineMutation(mutation)))),
404
+ stats: JSON.parse(
405
+ this.engine.binding.rustEngineApplyMutation(JSON.stringify(normalizeRustEngineMutation(mutation)))
406
+ ),
394
407
  dependencyInvalidated: !isRustIncrementalDependencyMutation(mutation.id)
395
408
  };
396
409
  } catch (error) {
@@ -402,16 +415,16 @@ var RustFormulaProjectionService = class {
402
415
  }
403
416
  }
404
417
  async syncFormulaDependencies(input) {
405
- return await this._ensureNativeLoaded(), JSON.parse(syncRustFormulaDependenciesOnRust(JSON.stringify(input)));
418
+ return await this._ensureNativeLoaded(), JSON.parse(this.engine.binding.rustEngineSyncFormulaDependencies(JSON.stringify(input)));
406
419
  }
407
420
  async markDirty(input) {
408
- return await this._ensureNativeLoaded(), JSON.parse(markRustFormulaDirtyOnRust(JSON.stringify(input)));
421
+ return await this._ensureNativeLoaded(), JSON.parse(this.engine.binding.rustEngineMarkFormulaDirty(JSON.stringify(input)));
409
422
  }
410
423
  async calculateDirty(maxIteration = 1) {
411
424
  await this._ensureNativeLoaded();
412
425
  try {
413
426
  let output = JSON.parse(
414
- executeDirtyFormulasOnRust(maxIteration, !1, !1, !0)
427
+ this.engine.binding.rustEngineExecuteDirtyFormulas(maxIteration, !1, !1, !0)
415
428
  );
416
429
  return rustExecutionOutputToFormulaCalculationPatch(output);
417
430
  } catch (error) {
@@ -426,7 +439,7 @@ var RustFormulaProjectionService = class {
426
439
  async reset() {
427
440
  await this._ensureNativeLoaded();
428
441
  try {
429
- return clearRustFormulaDirtyOnRust(), clearRustFormulaDependenciesOnRust(
442
+ return this.engine.binding.rustEngineClearFormulaDirty(), this.engine.binding.rustEngineClearFormulaDependencies(
430
443
  JSON.stringify({
431
444
  unitId: "",
432
445
  clearSheetFormulas: !0,
@@ -434,7 +447,11 @@ var RustFormulaProjectionService = class {
434
447
  clearOtherFormulas: !0
435
448
  })
436
449
  ), {
437
- stats: JSON.parse(loadSnapshotOnRust(JSON.stringify({ workbooks: [] })))
450
+ stats: JSON.parse(
451
+ this.engine.binding.rustEngineLoadSnapshot(
452
+ JSON.stringify({ workbooks: [] })
453
+ )
454
+ )
438
455
  };
439
456
  } catch (error) {
440
457
  return {
@@ -446,7 +463,7 @@ var RustFormulaProjectionService = class {
446
463
  async disposeWorkbook(unitId) {
447
464
  await this._ensureNativeLoaded();
448
465
  try {
449
- return { stats: JSON.parse(disposeWorkbookOnRust(unitId)) };
466
+ return { stats: JSON.parse(this.engine.binding.rustEngineDisposeWorkbook(unitId)) };
450
467
  } catch (error) {
451
468
  return {
452
469
  desync: createFormulaProjectionDesyncSignal("workbook-dispose-failed", error),
@@ -455,7 +472,7 @@ var RustFormulaProjectionService = class {
455
472
  }
456
473
  }
457
474
  async _ensureNativeLoaded() {
458
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0);
475
+ this._nativeLoaded || (await this.engine.initialize(), this._nativeLoaded = !0);
459
476
  }
460
477
  };
461
478
  function normalizeRustEngineMutation(mutation) {
@@ -989,19 +1006,6 @@ function isRecord(value) {
989
1006
  }
990
1007
 
991
1008
  // src/controllers/rust-engine-sync.controller.ts
992
- var rustEngineSyncState = {
993
- snapshotEpoch: 0,
994
- dependencyInvalidationEpoch: 0
995
- };
996
- function getRustEngineSyncState() {
997
- return { ...rustEngineSyncState };
998
- }
999
- function markRustSnapshotLoaded() {
1000
- rustEngineSyncState.snapshotEpoch += 1, rustEngineSyncState.dependencyInvalidationEpoch += 1;
1001
- }
1002
- function markRustFormulaDependenciesInvalidated() {
1003
- rustEngineSyncState.dependencyInvalidationEpoch += 1;
1004
- }
1005
1009
  function emitRustEngineSyncDebugEvent(event) {
1006
1010
  let hook = globalThis.__UNIVER_RUST_FORMULA_DEBUG_HOOK__;
1007
1011
  typeof hook == "function" && hook(event);
@@ -1041,6 +1045,17 @@ var RustEngineSyncController = class extends Disposable {
1041
1045
  this._initialize();
1042
1046
  }
1043
1047
  _commandService;
1048
+ engine = new RustFormulaEngineSession();
1049
+ _syncState = { snapshotEpoch: 0, dependencyInvalidationEpoch: 0 };
1050
+ getSyncState() {
1051
+ return { ...this._syncState };
1052
+ }
1053
+ _markSnapshotLoaded() {
1054
+ this._syncState.snapshotEpoch += 1, this._syncState.dependencyInvalidationEpoch += 1;
1055
+ }
1056
+ _markDependenciesInvalidated() {
1057
+ this._syncState.dependencyInvalidationEpoch += 1;
1058
+ }
1044
1059
  _nativeReady = !1;
1045
1060
  _snapshotLoaded = !1;
1046
1061
  _projectionLoadPromise = null;
@@ -1074,7 +1089,7 @@ var RustEngineSyncController = class extends Disposable {
1074
1089
  this._projectionDeltaBarrier = barrier;
1075
1090
  }
1076
1091
  async _loadProjection(workbooks) {
1077
- await loadNativeBinding(), this._nativeReady = !0;
1092
+ await this.engine.initialize(), this._nativeReady = !0;
1078
1093
  let serializeStartedAt = performance.now(), snapshot = serializeRuntimeWorkbookSnapshots(workbooks);
1079
1094
  this._loadSerializedSnapshot(snapshot, performance.now() - serializeStartedAt);
1080
1095
  }
@@ -1097,20 +1112,17 @@ var RustEngineSyncController = class extends Disposable {
1097
1112
  disposeProjectionWorkbook(unitId) {
1098
1113
  if (!(!this._nativeReady || !this._snapshotLoaded))
1099
1114
  try {
1100
- disposeWorkbookOnRust(unitId), markRustFormulaDependenciesInvalidated();
1115
+ this.engine.binding.rustEngineDisposeWorkbook(unitId), this._markDependenciesInvalidated();
1101
1116
  } catch {
1102
- this._markProjectionDesynced();
1117
+ this.markProjectionDesynced();
1103
1118
  }
1104
1119
  }
1105
1120
  dispose() {
1106
- if (super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, this._projectionDeltaBarrier = Promise.resolve(), !this._nativeReady) {
1107
- this._snapshotLoaded = !1;
1108
- return;
1109
- }
1121
+ super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, this._projectionDeltaBarrier = Promise.resolve();
1110
1122
  try {
1111
- disposeAllWorkbooksOnRust();
1123
+ this.engine.dispose();
1112
1124
  } catch {
1113
- this._markProjectionDesynced();
1125
+ this.markProjectionDesynced();
1114
1126
  return;
1115
1127
  }
1116
1128
  this._nativeReady = !1, this._snapshotLoaded = !1;
@@ -1118,7 +1130,7 @@ var RustEngineSyncController = class extends Disposable {
1118
1130
  _loadSerializedSnapshot(snapshot, serializeMs) {
1119
1131
  let precisionAsDisplayedWorkbookCount = snapshot.workbooks.filter(
1120
1132
  (workbook) => workbook.calculation?.fullPrecision === !1
1121
- ).length, displayPrecisionCellCount = countDisplayPrecisionCells(snapshot), pendingCountCoveredBySnapshot = this._pendingMutations.length, stringifyStartedAt = performance.now(), snapshotJson = JSON.stringify(snapshot), stringifyMs = performance.now() - stringifyStartedAt, snapshotBuffer = globalThis.Buffer?.from(snapshotJson), nativeStartedAt = performance.now(), nativeOutput = snapshotBuffer ? loadSnapshotBinaryOnRust(snapshotBuffer) : loadSnapshotOnRust(snapshotJson), nativeMs = performance.now() - nativeStartedAt, nativeTimings;
1133
+ ).length, displayPrecisionCellCount = countDisplayPrecisionCells(snapshot), pendingCountCoveredBySnapshot = this._pendingMutations.length, stringifyStartedAt = performance.now(), snapshotJson = JSON.stringify(snapshot), stringifyMs = performance.now() - stringifyStartedAt, snapshotBuffer = globalThis.Buffer?.from(snapshotJson), nativeStartedAt = performance.now(), nativeOutput = snapshotBuffer ? this.engine.binding.rustEngineLoadSnapshotBinary(snapshotBuffer) : this.engine.binding.rustEngineLoadSnapshot(snapshotJson), nativeMs = performance.now() - nativeStartedAt, nativeTimings;
1122
1134
  try {
1123
1135
  nativeTimings = JSON.parse(nativeOutput).timingsMs;
1124
1136
  } catch {
@@ -1137,7 +1149,7 @@ var RustEngineSyncController = class extends Disposable {
1137
1149
  transport: snapshotBuffer ? "binary-json" : "string-json",
1138
1150
  nativeTimings
1139
1151
  }
1140
- }), this._pendingMutations.splice(0, pendingCountCoveredBySnapshot), this._snapshotLoaded = !0, markRustSnapshotLoaded(), this._flushPendingMutations();
1152
+ }), this._pendingMutations.splice(0, pendingCountCoveredBySnapshot), this._snapshotLoaded = !0, this._markSnapshotLoaded(), this._flushPendingMutations();
1141
1153
  }
1142
1154
  _queueOrSyncMutation(mutation) {
1143
1155
  if (!this._nativeReady || !this._snapshotLoaded) {
@@ -1155,9 +1167,9 @@ var RustEngineSyncController = class extends Disposable {
1155
1167
  _syncMutation(mutation) {
1156
1168
  let totalStartedAt = performance.now(), stringifyStartedAt = performance.now(), payload = JSON.stringify(normalizeRustEngineMutation(mutation)), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now();
1157
1169
  try {
1158
- applyMutationOnRust(payload), isRustIncrementalDependencyMutation(mutation.id) || markRustFormulaDependenciesInvalidated();
1170
+ this.engine.binding.rustEngineApplyMutation(payload), isRustIncrementalDependencyMutation(mutation.id) || this._markDependenciesInvalidated();
1159
1171
  } catch {
1160
- this._markProjectionDesynced();
1172
+ this.markProjectionDesynced();
1161
1173
  } finally {
1162
1174
  emitRustEngineSyncDebugEvent({
1163
1175
  type: "applyMutation",
@@ -1173,7 +1185,11 @@ var RustEngineSyncController = class extends Disposable {
1173
1185
  });
1174
1186
  }
1175
1187
  }
1176
- _markProjectionDesynced() {
1188
+ /**
1189
+ * Marks the native projection as out of sync so the next mutation reloads it.
1190
+ * Also used by the projection controller when a background projection load fails.
1191
+ */
1192
+ markProjectionDesynced() {
1177
1193
  this._nativeReady = !1, this._snapshotLoaded = !1;
1178
1194
  }
1179
1195
  _shouldSyncMutation(command, options) {
@@ -1239,7 +1255,7 @@ import { ICalculateFormulaService } from "@univerjs/engine-formula";
1239
1255
  import { UniverProFormulaEnginePlugin } from "@univerjs-pro/engine-formula";
1240
1256
 
1241
1257
  // package.json
1242
- var name = "@univerjs-pro/engine-formula-rust", version = "1.0.0";
1258
+ var name = "@univerjs-pro/engine-formula-rust", version = "1.0.2";
1243
1259
 
1244
1260
  // src/controllers/rust-same-runtime-projection.controller.ts
1245
1261
  import {
@@ -1287,7 +1303,9 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
1287
1303
  UniverInstanceType.UNIVER_BASE
1288
1304
  ))
1289
1305
  this._rustEngineSyncController.setProjectionManagedTableUnit(base.getUnitId()), this._rememberBaseProjectionStructure(base.getSnapshot());
1290
- this._initialProjectionLoad = this._loadAllWorkbookProjections(), this.disposeWithMe(
1306
+ this._initialProjectionLoad = this._loadAllWorkbookProjections().catch(() => {
1307
+ this._rustEngineSyncController.markProjectionDesynced();
1308
+ }), this.disposeWithMe(
1291
1309
  toDisposable(
1292
1310
  this._univerInstanceService.getTypeOfUnitAdded$(UniverInstanceType.UNIVER_SHEET).subscribe(({ unit }) => {
1293
1311
  this._enqueueProjectionDelta(() => {
@@ -1909,14 +1927,19 @@ var RustCalculateFormulaService = class extends Disposable3 {
1909
1927
  this._runtimeService.setRuntimeFeatureRange(featureId, featureRange);
1910
1928
  }
1911
1929
  async execute(formulaDatasetConfig) {
1912
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), await this._rustEngineSyncController.waitForProjectionLoad(), this._externalFormulaDatasetConfig = formulaDatasetConfig, this._currentConfigService.load(formulaDatasetConfig), this._externalRequestGeneration++, this._externalInflight.clear(), this._externalCompleted.clear(), this._runtimeService.setFormulaExecuteStage(FormulaExecuteStageType.START), this._executionInProgressListener$.next(this._runtimeService.getRuntimeState()), this._runtimeService.reset();
1930
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), await this._rustEngineSyncController.waitForProjectionLoad(), this._externalFormulaDatasetConfig = formulaDatasetConfig, this._currentConfigService.load(formulaDatasetConfig), this._externalRequestGeneration++, this._externalInflight.clear(), this._externalCompleted.clear(), this._runtimeService.setFormulaExecuteStage(FormulaExecuteStageType.START), this._executionInProgressListener$.next(this._runtimeService.getRuntimeState()), this._runtimeService.reset();
1913
1931
  let cycleReferenceCount = Math.max(formulaDatasetConfig.maxIteration || 1, 1);
1914
1932
  await this._executeLock.acquire("FORMULA_EXECUTION_LOCK", async () => {
1915
1933
  this._runtimeService.setFormulaCycleIndex(0), await this._executeStep(cycleReferenceCount) > 0 ? this._runtimeService.markedAsSuccessfullyExecuted() : this._runtimeService.markedAsNoFunctionsExecuted(), this._runtimeService.setFormulaExecuteStage(FormulaExecuteStageType.CALCULATION_COMPLETED), this._executionInProgressListener$.next(this._runtimeService.getRuntimeState()), this._executionCompleteListener$.next(this._runtimeService.getAllRuntimeData()), this._runtimeService.reset();
1916
1934
  });
1917
1935
  }
1918
1936
  async _executeStep(maxIteration) {
1919
- let syncedFeatures = this._syncRustFormulaDependencies(void 0, !0), previousFeatureSignatures = this._featureSignatureMap(syncedFeatures), executeStartedAt = performance.now(), outputJson = executeDirtyFormulasOnRust(maxIteration, !1, !1, !0), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount = output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt;
1937
+ let syncedFeatures = this._syncRustFormulaDependencies(void 0, !0), previousFeatureSignatures = this._featureSignatureMap(syncedFeatures), executeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineExecuteDirtyFormulas(
1938
+ maxIteration,
1939
+ !1,
1940
+ !1,
1941
+ !0
1942
+ ), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount = output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt;
1920
1943
  output = await this._resolveExternalReferenceNeeds(output, maxIteration);
1921
1944
  let applyStartedAt = performance.now(), applyBreakdown = await this._applyRustDependencyOutput(output), applyMs = performance.now() - applyStartedAt;
1922
1945
  if (emitRustFormulaDebugEvent({
@@ -1952,7 +1975,12 @@ var RustCalculateFormulaService = class extends Disposable3 {
1952
1975
  this._markRustFormulaDirty(
1953
1976
  this._currentConfigService.getDirtyData(),
1954
1977
  this._dirtyFeatureMapFor(changedFeatures)
1955
- ), executeStartedAt = performance.now(), outputJson = executeDirtyFormulasOnRust(maxIteration, !1, !1, !0), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount += output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt, output = await this._resolveExternalReferenceNeeds(output, maxIteration), applyStartedAt = performance.now(), applyBreakdown = await this._applyRustDependencyOutput(output), applyMs = performance.now() - applyStartedAt, emitRustFormulaDebugEvent({
1978
+ ), executeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineExecuteDirtyFormulas(
1979
+ maxIteration,
1980
+ !1,
1981
+ !1,
1982
+ !0
1983
+ ), nativeAndSerializeMs = performance.now() - executeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), calculatedNodeCount += output.calculatedNodeCount, parseMs = performance.now() - parseStartedAt, output = await this._resolveExternalReferenceNeeds(output, maxIteration), applyStartedAt = performance.now(), applyBreakdown = await this._applyRustDependencyOutput(output), applyMs = performance.now() - applyStartedAt, emitRustFormulaDebugEvent({
1956
1984
  type: "executeDirtyFormulas",
1957
1985
  payload: {
1958
1986
  calculatedNodeCount: output.calculatedNodeCount,
@@ -1997,7 +2025,14 @@ var RustCalculateFormulaService = class extends Disposable3 {
1997
2025
  loadedRanges,
1998
2026
  this._superTableService
1999
2027
  ) === 0) break;
2000
- this._syncRustFormulaDependencies(), output = JSON.parse(executeDirtyFormulasOnRust(maxIteration, !1, !1, !0));
2028
+ this._syncRustFormulaDependencies(), output = JSON.parse(
2029
+ this._rustEngineSyncController.engine.binding.rustEngineExecuteDirtyFormulas(
2030
+ maxIteration,
2031
+ !1,
2032
+ !1,
2033
+ !0
2034
+ )
2035
+ );
2001
2036
  }
2002
2037
  return output;
2003
2038
  }
@@ -2171,7 +2206,7 @@ var RustCalculateFormulaService = class extends Disposable3 {
2171
2206
  };
2172
2207
  }
2173
2208
  _syncRustFormulaDependencies(dirtyUnitFeatureMapOverride, includeExternalReferences = !1) {
2174
- let syncState = getRustEngineSyncState(), externalReferences = includeExternalReferences ? this._externalFormulaDatasetConfig?.externalReferences ?? {} : void 0, externalReferenceSignature = externalReferences ? JSON.stringify(externalReferences) : this._syncedExternalReferenceSignature, shouldSendExternalReferences = includeExternalReferences && (externalReferenceSignature !== "{}" || this._syncedExternalReferenceSignature !== "{}"), rebuildSheetFormulas = this._syncedSnapshotEpoch !== syncState.snapshotEpoch || this._syncedDependencyInvalidationEpoch !== syncState.dependencyInvalidationEpoch || shouldSendExternalReferences, collectStartedAt = performance.now(), state = this._collectRustFormulaDependencySyncState(), collectMs = performance.now() - collectStartedAt;
2209
+ let syncState = this._rustEngineSyncController.getSyncState(), externalReferences = includeExternalReferences ? this._externalFormulaDatasetConfig?.externalReferences ?? {} : void 0, externalReferenceSignature = externalReferences ? JSON.stringify(externalReferences) : this._syncedExternalReferenceSignature, shouldSendExternalReferences = includeExternalReferences && (externalReferenceSignature !== "{}" || this._syncedExternalReferenceSignature !== "{}"), rebuildSheetFormulas = this._syncedSnapshotEpoch !== syncState.snapshotEpoch || this._syncedDependencyInvalidationEpoch !== syncState.dependencyInvalidationEpoch || shouldSendExternalReferences, collectStartedAt = performance.now(), state = this._collectRustFormulaDependencySyncState(), collectMs = performance.now() - collectStartedAt;
2175
2210
  if (!(shouldSendExternalReferences || rebuildSheetFormulas || state.featureCalculations.length > 0 || state.otherFormulas.length > 0))
2176
2211
  return emitRustFormulaDebugEvent({
2177
2212
  type: "syncDependencies",
@@ -2195,7 +2230,7 @@ var RustCalculateFormulaService = class extends Disposable3 {
2195
2230
  featureCalculations: state.featureCalculations,
2196
2231
  otherFormulas: state.otherFormulas,
2197
2232
  ...shouldSendExternalReferences ? { externalReferences } : {}
2198
- }), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = syncRustFormulaDependenciesOnRust(inputJson), nativeMs = performance.now() - nativeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), parseMs = performance.now() - parseStartedAt;
2233
+ }), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineSyncFormulaDependencies(inputJson), nativeMs = performance.now() - nativeStartedAt, parseStartedAt = performance.now(), output = JSON.parse(outputJson), parseMs = performance.now() - parseStartedAt;
2199
2234
  return emitRustFormulaDebugEvent({
2200
2235
  type: "syncDependencies",
2201
2236
  payload: {
@@ -2217,7 +2252,7 @@ var RustCalculateFormulaService = class extends Disposable3 {
2217
2252
  }
2218
2253
  _syncRustFormulaDependencyDefinitions() {
2219
2254
  let state = this._collectRustFormulaDependencySyncState();
2220
- return syncRustFormulaDependenciesOnRust(
2255
+ return this._rustEngineSyncController.engine.binding.rustEngineSyncFormulaDependencies(
2221
2256
  JSON.stringify({
2222
2257
  rebuildSheetFormulas: !1,
2223
2258
  featureCalculations: state.featureCalculations,
@@ -2292,7 +2327,7 @@ var RustCalculateFormulaService = class extends Disposable3 {
2292
2327
  dirtyUnitOtherFormulaMap: dirtyData.dirtyUnitOtherFormulaMap,
2293
2328
  dirtyNameMap: dirtyData.dirtyNameMap,
2294
2329
  dirtyDefinedNameMap: dirtyData.dirtyDefinedNameMap
2295
- }, stringifyStartedAt = performance.now(), inputJson = JSON.stringify(payload), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = markRustFormulaDirtyOnRust(inputJson), nativeMs = performance.now() - nativeStartedAt, rustTimings;
2330
+ }, stringifyStartedAt = performance.now(), inputJson = JSON.stringify(payload), stringifyMs = performance.now() - stringifyStartedAt, nativeStartedAt = performance.now(), outputJson = this._rustEngineSyncController.engine.binding.rustEngineMarkFormulaDirty(inputJson), nativeMs = performance.now() - nativeStartedAt, rustTimings;
2296
2331
  try {
2297
2332
  rustTimings = JSON.parse(outputJson).timings;
2298
2333
  } catch {
@@ -2474,7 +2509,7 @@ var RustCalculateFormulaService = class extends Disposable3 {
2474
2509
  });
2475
2510
  }
2476
2511
  async calculate(formulaString) {
2477
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0);
2512
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0);
2478
2513
  let unitId = "__rust_formula_calculate__", sheetId = "__sheet__", input = {
2479
2514
  config: { maxIteration: 1, intervalCount: DEFAULT_INTERVAL_COUNT },
2480
2515
  formulaData: {
@@ -2499,7 +2534,7 @@ var RustCalculateFormulaService = class extends Disposable3 {
2499
2534
  return JSON.parse(executeOnRust(JSON.stringify(input))).runtimeData?.[unitId]?.[sheetId]?.[0]?.[0] ?? null;
2500
2535
  }
2501
2536
  async executeFormulas(formulas, rowData) {
2502
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._currentConfigService.loadDataLite(rowData);
2537
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._currentConfigService.loadDataLite(rowData);
2503
2538
  let unitData = this._currentConfigService.getUnitData(), definedNames = {};
2504
2539
  for (let [unitId, names] of Object.entries(this._definedNamesService.getAllDefinedNames()))
2505
2540
  for (let [id, name2] of Object.entries(names))
@@ -2522,12 +2557,12 @@ var RustCalculateFormulaService = class extends Disposable3 {
2522
2557
  return this._formulaExecutionOutputToResultMap(formulas, output);
2523
2558
  }
2524
2559
  async getAllDependencyJson(_rowData) {
2525
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2560
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2526
2561
  let graph = this._getRustDependencyGraph(), inspect = this._getRustInspectGraph();
2527
2562
  return this._rustAllDependencyJson(graph, inspect);
2528
2563
  }
2529
2564
  async getCellDependencyJson(unitId, sheetId, row, column, _rowData) {
2530
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2565
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2531
2566
  let graph = this._getRustDependencyGraph(unitId), all = this._rustGraphDependencyJson(graph), current = all.find(
2532
2567
  (item) => item.unitId === unitId && item.subUnitId === sheetId && item.row === row && item.column === column
2533
2568
  );
@@ -2541,16 +2576,18 @@ var RustCalculateFormulaService = class extends Disposable3 {
2541
2576
  };
2542
2577
  }
2543
2578
  async getRangeDependents(unitRanges) {
2544
- this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2579
+ this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions();
2545
2580
  let graph = this._getRustDependencyGraph(), graphItems = this._rustGraphDependencyJson(graph), graphByCell = this._rustDependencyJsonByCell(graphItems), dirty = JSON.parse(
2546
- getRustDirtyDependenciesOnRust(JSON.stringify(this._serializeUnitRanges(unitRanges)))
2581
+ this._rustEngineSyncController.engine.binding.rustEngineGetDirtyDependencies(
2582
+ JSON.stringify(this._serializeUnitRanges(unitRanges))
2583
+ )
2547
2584
  );
2548
2585
  return this._uniqueDependencyJson(
2549
2586
  (dirty.direct ?? dirty.affected ?? []).map((cell) => graphByCell.get(this._cellKey(cell))).filter(Boolean)
2550
2587
  );
2551
2588
  }
2552
2589
  async getInRangeFormulas(unitRanges) {
2553
- return this._nativeLoaded || (await loadNativeBinding(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions(), this._rustGraphDependencyJson(this._getRustDependencyGraph()).filter(
2590
+ return this._nativeLoaded || (await this._rustEngineSyncController.engine.initialize(), this._nativeLoaded = !0), this._syncRustFormulaDependencyDefinitions(), this._rustGraphDependencyJson(this._getRustDependencyGraph()).filter(
2554
2591
  (item) => this._cellInUnitRanges(item.unitId, item.subUnitId, item.row, item.column, unitRanges)
2555
2592
  );
2556
2593
  }
@@ -2596,10 +2633,14 @@ var RustCalculateFormulaService = class extends Disposable3 {
2596
2633
  }), result;
2597
2634
  }
2598
2635
  _getRustDependencyGraph(unitId) {
2599
- return JSON.parse(buildRustDependencyGraphOnRust(unitId));
2636
+ return JSON.parse(
2637
+ this._rustEngineSyncController.engine.binding.rustEngineBuildDependencyGraph(unitId)
2638
+ );
2600
2639
  }
2601
2640
  _getRustInspectGraph() {
2602
- return JSON.parse(inspectRustFormulaDependencyGraphOnRust());
2641
+ return JSON.parse(
2642
+ this._rustEngineSyncController.engine.binding.rustEngineInspectFormulaDependencyGraph()
2643
+ );
2603
2644
  }
2604
2645
  _rustAllDependencyJson(graph, inspect) {
2605
2646
  let cellItems = this._rustGraphDependencyJson(graph), seen = new Set(cellItems.map((item) => item.treeId)), nonCellItems = (inspect.nodes ?? []).filter((item) => item.node.nodeType !== "cellFormula" && !seen.has(item.index)).map((item) => this._rustFormulaNodeToDependencyJson(item.index, item.node));
@@ -2805,6 +2846,7 @@ export {
2805
2846
  RUST_UPSERT_REFERENCE_DATA_MUTATION_ID,
2806
2847
  RustCalculateFormulaService,
2807
2848
  RustEngineSyncController,
2849
+ RustFormulaEngineSession,
2808
2850
  RustFormulaProjectionService,
2809
2851
  UniverRustFormulaEnginePlugin,
2810
2852
  analyzeNumberFormatBatch,
@@ -5,25 +5,7 @@ import { ExternalReferenceModel, IFormulaReferenceDataService, UniverProFormulaE
5
5
  import { Subject } from "rxjs";
6
6
  import { ISheetBlock, ISnapshot } from "@univerjs/protocol";
7
7
  //#region src/binding.d.ts
8
- interface INativeBinding {
9
- formulaEngineExecute(inputJson: string): string;
10
- formulaLexerTreeBuild(formula: string, transformSuffix?: boolean): string;
11
- formulaSequenceNodesBuild(formula: string): string;
12
- formulaCheckIfAddBracket(formula: string): number;
13
- rustNumfmtFormat(inputJson: string): string;
14
- rustNumfmtFormatBatch(inputJson: string): string;
15
- rustNumfmtParse(inputJson: string): string;
16
- rustNumfmtParseBatch(inputJson: string): string;
17
- rustNumfmtParseMatrixBatch(inputJson: string): string;
18
- rustNumfmtParseValue(inputJson: string): string;
19
- rustNumfmtAnalyzeFormat(inputJson: string): string;
20
- rustNumfmtAnalyzeBatch(inputJson: string): string;
21
- rustNumfmtFormatInfo(inputJson: string): string;
22
- rustNumfmtFormatDateInfo(inputJson: string): string;
23
- rustNumfmtFormatColor(inputJson: string): string;
24
- rustNumfmtDateToSerial(inputJson: string): string;
25
- rustNumfmtDateFromSerial(inputJson: string): string;
26
- rustNumfmtValidate(inputJson: string): string;
8
+ interface INativeFormulaEngine {
27
9
  rustEngineLoadSnapshot(snapshotJson: string): string;
28
10
  rustEngineLoadSnapshotBinary(snapshotBytes: Buffer): string;
29
11
  rustEngineLoadSingleSheetColumnarSnapshot(unitId: string, workbookName: string | undefined | null, sheetId: string, sheetName: string | undefined | null, rowCount: number, columnCount: number, rows: Buffer, cols: Buffer, valueTags: Buffer, numbers: Buffer, valueStringOffsets: Buffer, valueStringBytes: Buffer, formulaOffsets: Buffer, formulaBytes: Buffer): string;
@@ -45,6 +27,28 @@ interface INativeBinding {
45
27
  rustEngineClearFormulaDirty(): string;
46
28
  rustEngineExecuteDirtyFormulas(maxIteration?: number, includeCalculatedNodes?: boolean, includeRuntimeData?: boolean, includeResultBatches?: boolean): string;
47
29
  rustEngineGetFormulaNumberResultsColumnar(unitId: string, sheetId: string, startColumn?: number, endColumn?: number): Buffer;
30
+ dispose(): void;
31
+ }
32
+ interface INativeBinding extends Omit<INativeFormulaEngine, 'dispose'> {
33
+ formulaEngineExecute(inputJson: string): string;
34
+ formulaLexerTreeBuild(formula: string, transformSuffix?: boolean): string;
35
+ formulaSequenceNodesBuild(formula: string): string;
36
+ formulaCheckIfAddBracket(formula: string): number;
37
+ rustNumfmtFormat(inputJson: string): string;
38
+ rustNumfmtFormatBatch(inputJson: string): string;
39
+ rustNumfmtParse(inputJson: string): string;
40
+ rustNumfmtParseBatch(inputJson: string): string;
41
+ rustNumfmtParseMatrixBatch(inputJson: string): string;
42
+ rustNumfmtParseValue(inputJson: string): string;
43
+ rustNumfmtAnalyzeFormat(inputJson: string): string;
44
+ rustNumfmtAnalyzeBatch(inputJson: string): string;
45
+ rustNumfmtFormatInfo(inputJson: string): string;
46
+ rustNumfmtFormatDateInfo(inputJson: string): string;
47
+ rustNumfmtFormatColor(inputJson: string): string;
48
+ rustNumfmtDateToSerial(inputJson: string): string;
49
+ rustNumfmtDateFromSerial(inputJson: string): string;
50
+ rustNumfmtValidate(inputJson: string): string;
51
+ RustFormulaEngine: new () => INativeFormulaEngine;
48
52
  rustMaterializeWorkbookSnapshot(workbookJson: Buffer, unitId: string, rev: number, dirtyInputJson?: string): Promise<INativeMaterializedWorkbook>;
49
53
  }
50
54
  interface INativeMaterializedBlock {
@@ -85,6 +89,14 @@ declare function markRustFormulaDirtyOnRust(inputJson: string): string;
85
89
  declare function clearRustFormulaDependenciesOnRust(inputJson: string): string;
86
90
  declare function clearRustFormulaDirtyOnRust(): string;
87
91
  declare function materializeWorkbookSnapshotOnRust(workbookJson: Buffer, unitId: string, rev: number, dirtyInputJson?: string): Promise<INativeMaterializedWorkbook>;
92
+ /** Owns one native store. Loading and disposal never touch another session. */
93
+ declare class RustFormulaEngineSession {
94
+ private _engine;
95
+ private _disposed;
96
+ initialize(): Promise<void>;
97
+ get binding(): INativeFormulaEngine;
98
+ dispose(): void;
99
+ }
88
100
  //#endregion
89
101
  //#region src/types.d.ts
90
102
  /**
@@ -569,6 +581,8 @@ declare function createProjectionWorkbookUpsertMutation(input: IRustProjectionWo
569
581
  declare function rustExecutionOutputToFormulaCalculationPatch(output: IRustFormulaDependencyExecutionOutput): IFormulaCalculationPatch;
570
582
  declare function createFormulaProjectionDesyncSignal(reason: string, error: unknown, mutationId?: string): IFormulaProjectionDesyncSignal;
571
583
  declare class RustFormulaProjectionService {
584
+ readonly engine: RustFormulaEngineSession;
585
+ dispose(): void;
572
586
  private _nativeLoaded;
573
587
  load(workbooks: readonly IRustProjectionWorkbookInput[]): Promise<IRustFormulaProjectionLoadResult>;
574
588
  applyMutation(mutation: IRustEngineMutation): Promise<IRustFormulaProjectionMutationResult>;
@@ -590,6 +604,10 @@ declare class RustFormulaProjectionService {
590
604
  }
591
605
  //#endregion
592
606
  //#region src/controllers/rust-engine-sync.controller.d.ts
607
+ interface IRustEngineSyncState {
608
+ snapshotEpoch: number;
609
+ dependencyInvalidationEpoch: number;
610
+ }
593
611
  /**
594
612
  * Keeps Rust's in-memory formula workbook projection aligned with Univer.
595
613
  *
@@ -599,6 +617,11 @@ declare class RustFormulaProjectionService {
599
617
  */
600
618
  declare class RustEngineSyncController extends Disposable {
601
619
  private readonly _commandService;
620
+ readonly engine: RustFormulaEngineSession;
621
+ private readonly _syncState;
622
+ getSyncState(): IRustEngineSyncState;
623
+ private _markSnapshotLoaded;
624
+ private _markDependenciesInvalidated;
602
625
  private _nativeReady;
603
626
  private _snapshotLoaded;
604
627
  private _projectionLoadPromise;
@@ -627,7 +650,11 @@ declare class RustEngineSyncController extends Disposable {
627
650
  private _queueOrSyncMutation;
628
651
  private _flushPendingMutations;
629
652
  private _syncMutation;
630
- private _markProjectionDesynced;
653
+ /**
654
+ * Marks the native projection as out of sync so the next mutation reloads it.
655
+ * Also used by the projection controller when a background projection load fails.
656
+ */
657
+ markProjectionDesynced(): void;
631
658
  private _shouldSyncMutation;
632
659
  private _serializeMutation;
633
660
  }
@@ -940,4 +967,4 @@ interface IMaterializationCalculationStats {
940
967
  }
941
968
  declare function materializeWorkbookSnapshot(workbook: IWorkbookData, unitID: string, rev: number, dirtyInput?: IRustFormulaDependencyDirtyInput): Promise<IMaterializedWorkbookSnapshot>;
942
969
  //#endregion
943
- export { type IAnalyzeNumberFormatBatchInput, type IAnalyzeNumberFormatBatchOutput, ICellValue, ICycleDependencyInfo, IDefinedName, IExecutionError, type IFormatNumberBatchInput, type IFormatNumberBatchOutput, type IFormulaCalculationError, type IFormulaCalculationPatch, IFormulaEngineConfig, IFormulaExecutionInput, IFormulaExecutionOutput, type IFormulaProjectionDesyncSignal, type IMaterializationCalculationStats, type IMaterializedWorkbookSnapshot, type INumberFormatAnalysis, type INumberFormatDiagnostic, type INumberFormatOptions, type IObjectArrayPrimitiveType, type IObjectMatrixPrimitiveType, type IParseNumberFormatBatchInput, type IParseNumberFormatBatchOutput, type IParseNumberFormatMatrixBatchInput, type IParseNumberFormatMatrixBatchOutput, type IParseNumberFormatMatrixCell, type IParsedNumberFormatMatrixValue, type IParsedNumberFormatValue, IRange, IRustCalculateFormulaService, IRustDefinedNameSnapshot, IRustDependencyCalculationPlanItem, IRustDependencyCalculationTree, IRustDependencyCell, IRustDependencyDirtyResult, IRustDependencyGraph, IRustDependencyNode, IRustDependencyRange, IRustEngineModelStats, IRustEngineMutation, IRustEngineSnapshot, IRustExternalFeatureCalculation, IRustExternalLinkSnapshot, IRustExternalOtherFormula, IRustExternalSheetSnapshot, IRustFormulaDataItem, IRustFormulaDependencyClearInput, IRustFormulaDependencyDirtyInput, IRustFormulaDependencyDirtyOutput, IRustFormulaDependencyExecutionOutput, IRustFormulaDependencyInspectGraph, IRustFormulaDependencyInspectNode, IRustFormulaDependencyNodeOutput, IRustFormulaDependencySyncInput, IRustFormulaDependencySyncOutput, type IRustFormulaProjectionLoadResult, type IRustFormulaProjectionMutationResult, IRustFormulaStoreState, type IRustProjectionWorkbookInput, IRustResourceSnapshot, IRustSheetSnapshot, IRustSheetState, IRustTableSnapshot, IRustVisibilityData, IRustWorkbookCalculationSnapshot, IRustWorkbookSnapshot, ISheetData, IUnitRange, type IUniverRustFormulaEngineConfig, type NumberFormatDateSystem, RUST_FORMULA_RELEVANT_MUTATIONS, RUST_INCREMENTAL_DEPENDENCY_MUTATIONS, RUST_UPSERT_PROJECTION_WORKBOOK_MUTATION_ID, RUST_UPSERT_REFERENCE_DATA_MUTATION_ID, RustCalculateFormulaService, RustEngineSyncController, RustFormulaProjectionService, UniverRustFormulaEnginePlugin, analyzeNumberFormatBatch, applyMutationOnRust, buildLexerTreeOnRust, buildRustDependencyGraphOnRust, buildSequenceNodesOnRust, checkIfAddBracketOnRust, clearRustFormulaDependenciesOnRust, clearRustFormulaDirtyOnRust, createFormulaProjectionDesyncSignal, createProjectionWorkbookUpsertMutation, disposeAllWorkbooksOnRust, disposeWorkbookOnRust, executeOnRust, formatNumberBatch, getNativeBindingSource, getRustCellOnRust, getRustDirtyDependenciesOnRust, getRustFormulaDataOnRust, getRustModelStats, getRustSheetStateOnRust, isRustFormulaRelevantMutation, isRustIncrementalDependencyMutation, loadNativeBinding, loadSnapshotOnRust, markRustFormulaDirtyOnRust, materializeWorkbookSnapshot, materializeWorkbookSnapshotOnRust, parseNumberFormatBatch, parseNumberFormatMatrixBatch, rustExecutionOutputToFormulaCalculationPatch, serializeRuntimeWorkbookSnapshot, serializeRuntimeWorkbookSnapshots, syncRustFormulaDependenciesOnRust };
970
+ export { type IAnalyzeNumberFormatBatchInput, type IAnalyzeNumberFormatBatchOutput, ICellValue, ICycleDependencyInfo, IDefinedName, IExecutionError, type IFormatNumberBatchInput, type IFormatNumberBatchOutput, type IFormulaCalculationError, type IFormulaCalculationPatch, IFormulaEngineConfig, IFormulaExecutionInput, IFormulaExecutionOutput, type IFormulaProjectionDesyncSignal, type IMaterializationCalculationStats, type IMaterializedWorkbookSnapshot, type INativeFormulaEngine, type INumberFormatAnalysis, type INumberFormatDiagnostic, type INumberFormatOptions, type IObjectArrayPrimitiveType, type IObjectMatrixPrimitiveType, type IParseNumberFormatBatchInput, type IParseNumberFormatBatchOutput, type IParseNumberFormatMatrixBatchInput, type IParseNumberFormatMatrixBatchOutput, type IParseNumberFormatMatrixCell, type IParsedNumberFormatMatrixValue, type IParsedNumberFormatValue, IRange, IRustCalculateFormulaService, IRustDefinedNameSnapshot, IRustDependencyCalculationPlanItem, IRustDependencyCalculationTree, IRustDependencyCell, IRustDependencyDirtyResult, IRustDependencyGraph, IRustDependencyNode, IRustDependencyRange, IRustEngineModelStats, IRustEngineMutation, IRustEngineSnapshot, IRustExternalFeatureCalculation, IRustExternalLinkSnapshot, IRustExternalOtherFormula, IRustExternalSheetSnapshot, IRustFormulaDataItem, IRustFormulaDependencyClearInput, IRustFormulaDependencyDirtyInput, IRustFormulaDependencyDirtyOutput, IRustFormulaDependencyExecutionOutput, IRustFormulaDependencyInspectGraph, IRustFormulaDependencyInspectNode, IRustFormulaDependencyNodeOutput, IRustFormulaDependencySyncInput, IRustFormulaDependencySyncOutput, type IRustFormulaProjectionLoadResult, type IRustFormulaProjectionMutationResult, IRustFormulaStoreState, type IRustProjectionWorkbookInput, IRustResourceSnapshot, IRustSheetSnapshot, IRustSheetState, IRustTableSnapshot, IRustVisibilityData, IRustWorkbookCalculationSnapshot, IRustWorkbookSnapshot, ISheetData, IUnitRange, type IUniverRustFormulaEngineConfig, type NumberFormatDateSystem, RUST_FORMULA_RELEVANT_MUTATIONS, RUST_INCREMENTAL_DEPENDENCY_MUTATIONS, RUST_UPSERT_PROJECTION_WORKBOOK_MUTATION_ID, RUST_UPSERT_REFERENCE_DATA_MUTATION_ID, RustCalculateFormulaService, RustEngineSyncController, RustFormulaEngineSession, RustFormulaProjectionService, UniverRustFormulaEnginePlugin, analyzeNumberFormatBatch, applyMutationOnRust, buildLexerTreeOnRust, buildRustDependencyGraphOnRust, buildSequenceNodesOnRust, checkIfAddBracketOnRust, clearRustFormulaDependenciesOnRust, clearRustFormulaDirtyOnRust, createFormulaProjectionDesyncSignal, createProjectionWorkbookUpsertMutation, disposeAllWorkbooksOnRust, disposeWorkbookOnRust, executeOnRust, formatNumberBatch, getNativeBindingSource, getRustCellOnRust, getRustDirtyDependenciesOnRust, getRustFormulaDataOnRust, getRustModelStats, getRustSheetStateOnRust, isRustFormulaRelevantMutation, isRustIncrementalDependencyMutation, loadNativeBinding, loadSnapshotOnRust, markRustFormulaDirtyOnRust, materializeWorkbookSnapshot, materializeWorkbookSnapshotOnRust, parseNumberFormatBatch, parseNumberFormatMatrixBatch, rustExecutionOutputToFormulaCalculationPatch, serializeRuntimeWorkbookSnapshot, serializeRuntimeWorkbookSnapshots, syncRustFormulaDependenciesOnRust };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "author": "DreamNum Co., Ltd. <developer@univer.ai>",
3
3
  "dependencies": {
4
- "@univerjs-pro/engine-formula": "1.0.0",
5
- "@univerjs-pro/engine-formula-rust-binding": "1.0.0",
6
- "@univerjs/core": "1.0.0",
7
- "@univerjs/engine-formula": "1.0.0",
8
- "@univerjs/protocol": "1.0.0"
4
+ "@univerjs-pro/engine-formula": "1.0.2",
5
+ "@univerjs-pro/engine-formula-rust-binding": "1.0.1",
6
+ "@univerjs/core": "1.0.2",
7
+ "@univerjs/engine-formula": "1.0.2",
8
+ "@univerjs/protocol": "1.0.2"
9
9
  },
10
10
  "description": "Rust-backed formula engine plugin for Univer",
11
11
  "files": [
@@ -20,7 +20,7 @@
20
20
  "url": "https://github.com/dream-num/univer-rs"
21
21
  },
22
22
  "type": "module",
23
- "version": "1.0.0",
23
+ "version": "1.0.2",
24
24
  "main": "./lib/cjs/index.cjs",
25
25
  "module": "./lib/es/index.js",
26
26
  "types": "./lib/types/index.d.ts",