@univerjs-pro/engine-formula-rust 1.0.0-insiders.20260809-70eefdd → 1.0.0-rc.0
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 +190 -59
- package/lib/es/index.js +192 -59
- package/lib/types/index.d.ts +2 -0
- package/package.json +6 -6
package/lib/cjs/index.cjs
CHANGED
|
@@ -246,7 +246,7 @@ var import_core2 = require("@univerjs/core");
|
|
|
246
246
|
|
|
247
247
|
// src/services/rust-formula-projection.service.ts
|
|
248
248
|
var import_core = require("@univerjs/core");
|
|
249
|
-
var XLSX_WORKBOOK_CALCULATION_RESOURCE = "UNIVER_CLI_XLSX_WORKBOOK_CALCULATION_PLUGIN", EXTERNAL_DATA_RESOURCE = "SHEET_EXTERNAL_DATA_PLUGIN", EXTERNAL_DATA_SIGNATURE = "external_data", RUST_UPSERT_REFERENCE_DATA_MUTATION_ID = "formula.mutation.upsert-reference-data", RUST_UPSERT_PROJECTION_WORKBOOK_MUTATION_ID = "formula.mutation.upsert-projection-workbook", RUST_FORMULA_RELEVANT_MUTATIONS = /* @__PURE__ */ new Set([
|
|
249
|
+
var XLSX_WORKBOOK_CALCULATION_RESOURCE = "UNIVER_CLI_XLSX_WORKBOOK_CALCULATION_PLUGIN", EXTERNAL_DATA_RESOURCE = "SHEET_EXTERNAL_DATA_PLUGIN", EXTERNAL_DATA_SIGNATURE = "external_data", RUST_UPSERT_REFERENCE_DATA_MUTATION_ID = "formula.mutation.upsert-reference-data", RUST_UPSERT_PROJECTION_WORKBOOK_MUTATION_ID = "formula.mutation.upsert-projection-workbook", RUST_SET_SUPER_TABLES_MUTATION_ID = "formula.mutation.set-super-tables", RUST_FORMULA_RELEVANT_MUTATIONS = /* @__PURE__ */ new Set([
|
|
250
250
|
"sheet.mutation.set-range-values",
|
|
251
251
|
"sheet.mutation.insert-row",
|
|
252
252
|
"sheet.mutation.insert-col",
|
|
@@ -273,6 +273,7 @@ var XLSX_WORKBOOK_CALCULATION_RESOURCE = "UNIVER_CLI_XLSX_WORKBOOK_CALCULATION_P
|
|
|
273
273
|
"formula.mutation.set-image-formula-data",
|
|
274
274
|
"formula.mutation.set-other-formula",
|
|
275
275
|
"formula.mutation.set-super-table",
|
|
276
|
+
RUST_SET_SUPER_TABLES_MUTATION_ID,
|
|
276
277
|
"formula.mutation.set-super-table-option",
|
|
277
278
|
"formula.mutation.remove-defined-name",
|
|
278
279
|
"formula.mutation.remove-feature-calculation",
|
|
@@ -508,13 +509,26 @@ var RustFormulaProjectionService = class {
|
|
|
508
509
|
}
|
|
509
510
|
};
|
|
510
511
|
function normalizeRustEngineMutation(mutation) {
|
|
511
|
-
let params = mutation.id === "formula.mutation.set-super-table" ? normalizeSetSuperTableMutationParams(mutation.params) : mutation.params ?? {};
|
|
512
|
+
let params = mutation.id === "formula.mutation.set-super-table" ? normalizeSetSuperTableMutationParams(mutation.params) : mutation.id === RUST_SET_SUPER_TABLES_MUTATION_ID ? normalizeSetSuperTablesMutationParams(mutation.params) : mutation.params ?? {};
|
|
512
513
|
return {
|
|
513
514
|
id: mutation.id,
|
|
514
515
|
params,
|
|
515
516
|
dirtyRanges: Array.isArray(mutation.dirtyRanges) ? mutation.dirtyRanges : []
|
|
516
517
|
};
|
|
517
518
|
}
|
|
519
|
+
function normalizeSetSuperTablesMutationParams(params) {
|
|
520
|
+
return !isRecord(params) || typeof params.unitId != "string" || !Array.isArray(params.tables) ? params ?? {} : {
|
|
521
|
+
...params,
|
|
522
|
+
tables: params.tables.map((entry) => {
|
|
523
|
+
let normalized = normalizeSetSuperTableMutationParams(
|
|
524
|
+
isRecord(entry) ? { ...entry, unitId: params.unitId } : entry
|
|
525
|
+
);
|
|
526
|
+
if (!isRecord(normalized)) return normalized;
|
|
527
|
+
let { unitId: _unitId, ...table } = normalized;
|
|
528
|
+
return table;
|
|
529
|
+
})
|
|
530
|
+
};
|
|
531
|
+
}
|
|
518
532
|
function normalizeSetSuperTableMutationParams(params) {
|
|
519
533
|
if (!isRecord(params) || !isRecord(params.reference))
|
|
520
534
|
return params ?? {};
|
|
@@ -1082,6 +1096,7 @@ var RustEngineSyncController = class extends import_core2.Disposable {
|
|
|
1082
1096
|
_nativeReady = !1;
|
|
1083
1097
|
_snapshotLoaded = !1;
|
|
1084
1098
|
_projectionLoadPromise = null;
|
|
1099
|
+
_projectionDeltaBarrier = Promise.resolve();
|
|
1085
1100
|
_pendingMutations = [];
|
|
1086
1101
|
_projectionManagedTableUnits = /* @__PURE__ */ new Set();
|
|
1087
1102
|
_initialize() {
|
|
@@ -1102,6 +1117,13 @@ var RustEngineSyncController = class extends import_core2.Disposable {
|
|
|
1102
1117
|
}
|
|
1103
1118
|
async waitForProjectionLoad() {
|
|
1104
1119
|
await this._projectionLoadPromise;
|
|
1120
|
+
let barrier;
|
|
1121
|
+
do
|
|
1122
|
+
barrier = this._projectionDeltaBarrier, await barrier;
|
|
1123
|
+
while (barrier !== this._projectionDeltaBarrier);
|
|
1124
|
+
}
|
|
1125
|
+
setProjectionDeltaBarrier(barrier) {
|
|
1126
|
+
this._projectionDeltaBarrier = barrier;
|
|
1105
1127
|
}
|
|
1106
1128
|
async _loadProjection(workbooks) {
|
|
1107
1129
|
await loadNativeBinding(), this._nativeReady = !0;
|
|
@@ -1133,7 +1155,7 @@ var RustEngineSyncController = class extends import_core2.Disposable {
|
|
|
1133
1155
|
}
|
|
1134
1156
|
}
|
|
1135
1157
|
dispose() {
|
|
1136
|
-
if (super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, !this._nativeReady) {
|
|
1158
|
+
if (super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, this._projectionDeltaBarrier = Promise.resolve(), !this._nativeReady) {
|
|
1137
1159
|
this._snapshotLoaded = !1;
|
|
1138
1160
|
return;
|
|
1139
1161
|
}
|
|
@@ -1267,7 +1289,7 @@ async function analyzeNumberFormatBatch(input) {
|
|
|
1267
1289
|
var import_core5 = require("@univerjs/core"), import_engine_formula4 = require("@univerjs/engine-formula"), import_engine_formula5 = require("@univerjs-pro/engine-formula");
|
|
1268
1290
|
|
|
1269
1291
|
// package.json
|
|
1270
|
-
var name = "@univerjs-pro/engine-formula-rust", version = "1.0.0-
|
|
1292
|
+
var name = "@univerjs-pro/engine-formula-rust", version = "1.0.0-rc.0";
|
|
1271
1293
|
|
|
1272
1294
|
// src/controllers/rust-same-runtime-projection.controller.ts
|
|
1273
1295
|
var import_core3 = require("@univerjs/core"), import_engine_formula = require("@univerjs/engine-formula");
|
|
@@ -1290,11 +1312,12 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1290
1312
|
_activeDirtyManagerService;
|
|
1291
1313
|
_initialProjectionLoad = Promise.resolve();
|
|
1292
1314
|
_projectionDeltaQueue = Promise.resolve();
|
|
1315
|
+
_baseProjectionStructures = /* @__PURE__ */ new Map();
|
|
1293
1316
|
_initialize() {
|
|
1294
1317
|
for (let base of this._univerInstanceService.getAllUnitsForType(
|
|
1295
1318
|
import_core3.UniverInstanceType.UNIVER_BASE
|
|
1296
1319
|
))
|
|
1297
|
-
this._rustEngineSyncController.setProjectionManagedTableUnit(base.getUnitId());
|
|
1320
|
+
this._rustEngineSyncController.setProjectionManagedTableUnit(base.getUnitId()), this._rememberBaseProjectionStructure(base.getSnapshot());
|
|
1298
1321
|
this._initialProjectionLoad = this._loadAllWorkbookProjections(), this.disposeWithMe(
|
|
1299
1322
|
(0, import_core3.toDisposable)(
|
|
1300
1323
|
this._univerInstanceService.getTypeOfUnitAdded$(import_core3.UniverInstanceType.UNIVER_SHEET).subscribe(({ unit }) => {
|
|
@@ -1309,7 +1332,7 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1309
1332
|
), this.disposeWithMe(
|
|
1310
1333
|
(0, import_core3.toDisposable)(
|
|
1311
1334
|
this._univerInstanceService.getTypeOfUnitAdded$(import_core3.UniverInstanceType.UNIVER_BASE).subscribe(({ unit }) => {
|
|
1312
|
-
this._rustEngineSyncController.setProjectionManagedTableUnit(unit.getUnitId()), this._enqueueProjectionDelta(() => this._upsertBaseProjection(unit.getUnitId()));
|
|
1335
|
+
this._rustEngineSyncController.setProjectionManagedTableUnit(unit.getUnitId()), this._rememberBaseProjectionStructure(unit.getSnapshot()), this._enqueueProjectionDelta(() => this._upsertBaseProjection(unit.getUnitId()));
|
|
1313
1336
|
})
|
|
1314
1337
|
)
|
|
1315
1338
|
), this.disposeWithMe(
|
|
@@ -1319,7 +1342,7 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1319
1342
|
), this.disposeWithMe(
|
|
1320
1343
|
(0, import_core3.toDisposable)(
|
|
1321
1344
|
this._univerInstanceService.getTypeOfUnitDisposed$(import_core3.UniverInstanceType.UNIVER_BASE).subscribe((base) => {
|
|
1322
|
-
this._rustEngineSyncController.unsetProjectionManagedTableUnit(base.getUnitId()), this._enqueueProjectionDelta(
|
|
1345
|
+
this._baseProjectionStructures.delete(base.getUnitId()), this._rustEngineSyncController.unsetProjectionManagedTableUnit(base.getUnitId()), this._enqueueProjectionDelta(
|
|
1323
1346
|
() => this._rustEngineSyncController.disposeProjectionWorkbook(base.getUnitId())
|
|
1324
1347
|
);
|
|
1325
1348
|
})
|
|
@@ -1343,7 +1366,7 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1343
1366
|
if (!this._disposed)
|
|
1344
1367
|
return task();
|
|
1345
1368
|
}).catch(() => {
|
|
1346
|
-
});
|
|
1369
|
+
}), this._rustEngineSyncController.setProjectionDeltaBarrier(this._projectionDeltaQueue);
|
|
1347
1370
|
}
|
|
1348
1371
|
async _syncBaseMutation(command) {
|
|
1349
1372
|
if (!hasUnitId2(command.params)) return;
|
|
@@ -1352,7 +1375,65 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1352
1375
|
this._applyBaseDirtyRanges(unitId, dirtyRanges);
|
|
1353
1376
|
return;
|
|
1354
1377
|
}
|
|
1355
|
-
await this._upsertBaseProjection(unitId);
|
|
1378
|
+
hasStructureInvalidation && this._isBaseProjectionStructureUnchanged(unitId) || hasStructureInvalidation && this._applyBaseFieldInsertion(unitId, dirtyRanges) || await this._upsertBaseProjection(unitId);
|
|
1379
|
+
}
|
|
1380
|
+
_applyBaseFieldInsertion(unitId, dirtyRanges) {
|
|
1381
|
+
let base = this._univerInstanceService.getUnit(unitId, import_core3.UniverInstanceType.UNIVER_BASE), previous = this._baseProjectionStructures.get(unitId);
|
|
1382
|
+
if (!base || !previous) return !1;
|
|
1383
|
+
let snapshot = base.getSnapshot(), insertion = findSingleBaseFieldInsertion(previous, snapshot);
|
|
1384
|
+
if (!insertion) return !1;
|
|
1385
|
+
let projectionData = this._getBaseProjectionData(unitId), sheet = projectionData?.calculationData.allUnitData[unitId]?.[insertion.tableId];
|
|
1386
|
+
if (!projectionData || !sheet) return !1;
|
|
1387
|
+
let formulaData = projectionData.formulaData[unitId]?.[insertion.tableId], cellValue = {};
|
|
1388
|
+
for (let row = 0; row < sheet.rowCount; row++) {
|
|
1389
|
+
let value = sheet.cellData.getValue(row, insertion.column), formula = formulaData?.[row]?.[insertion.column];
|
|
1390
|
+
cellValue[row] = {
|
|
1391
|
+
[insertion.column]: formula ? { ...value, ...formula } : value ?? null
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
let insertedRange = {
|
|
1395
|
+
startRow: 0,
|
|
1396
|
+
endRow: Math.max(0, sheet.rowCount - 1),
|
|
1397
|
+
startColumn: insertion.column,
|
|
1398
|
+
endColumn: insertion.column
|
|
1399
|
+
};
|
|
1400
|
+
return this._rustEngineSyncController.applyProjectionMutation({
|
|
1401
|
+
id: "sheet.mutation.insert-col",
|
|
1402
|
+
params: {
|
|
1403
|
+
unitId,
|
|
1404
|
+
subUnitId: insertion.tableId,
|
|
1405
|
+
range: insertedRange
|
|
1406
|
+
},
|
|
1407
|
+
dirtyRanges: []
|
|
1408
|
+
}), this._rustEngineSyncController.applyProjectionMutation({
|
|
1409
|
+
id: "sheet.mutation.set-range-values",
|
|
1410
|
+
params: {
|
|
1411
|
+
unitId,
|
|
1412
|
+
subUnitId: insertion.tableId,
|
|
1413
|
+
cellValue
|
|
1414
|
+
},
|
|
1415
|
+
dirtyRanges: [
|
|
1416
|
+
{
|
|
1417
|
+
unitId,
|
|
1418
|
+
sheetId: insertion.tableId,
|
|
1419
|
+
range: insertedRange
|
|
1420
|
+
}
|
|
1421
|
+
]
|
|
1422
|
+
}), this._rustEngineSyncController.applyProjectionMutation({
|
|
1423
|
+
id: RUST_SET_SUPER_TABLES_MUTATION_ID,
|
|
1424
|
+
params: {
|
|
1425
|
+
unitId,
|
|
1426
|
+
tables: this._getBaseTableEntries(
|
|
1427
|
+
insertion.tableId,
|
|
1428
|
+
snapshot,
|
|
1429
|
+
(0, import_core3.createBaseFormulaTableNameMap)(snapshot)
|
|
1430
|
+
).map(([tableName, reference]) => ({
|
|
1431
|
+
tableName,
|
|
1432
|
+
reference
|
|
1433
|
+
}))
|
|
1434
|
+
},
|
|
1435
|
+
dirtyRanges: []
|
|
1436
|
+
}), dirtyRanges.length > 0 && this._applyBaseDirtyRanges(unitId, dirtyRanges), this._rememberBaseProjectionStructure(snapshot), !0;
|
|
1356
1437
|
}
|
|
1357
1438
|
_applyBaseDirtyRanges(unitId, dirtyRanges) {
|
|
1358
1439
|
let projectionData = this._getBaseProjectionData(unitId);
|
|
@@ -1394,6 +1475,15 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1394
1475
|
formulaData
|
|
1395
1476
|
);
|
|
1396
1477
|
workbook && this._rustEngineSyncController.upsertProjectionWorkbook(workbook);
|
|
1478
|
+
let base = this._univerInstanceService.getUnit(unitId, import_core3.UniverInstanceType.UNIVER_BASE);
|
|
1479
|
+
base && this._rememberBaseProjectionStructure(base.getSnapshot());
|
|
1480
|
+
}
|
|
1481
|
+
_rememberBaseProjectionStructure(snapshot) {
|
|
1482
|
+
this._baseProjectionStructures.set(snapshot.id, createBaseProjectionStructure(snapshot));
|
|
1483
|
+
}
|
|
1484
|
+
_isBaseProjectionStructureUnchanged(unitId) {
|
|
1485
|
+
let base = this._univerInstanceService.getUnit(unitId, import_core3.UniverInstanceType.UNIVER_BASE), previous = this._baseProjectionStructures.get(unitId);
|
|
1486
|
+
return !!(base && previous && isSameBaseProjectionStructure(previous, createBaseProjectionStructure(base.getSnapshot())));
|
|
1397
1487
|
}
|
|
1398
1488
|
_getBaseProjectionData(unitId) {
|
|
1399
1489
|
let base = this._univerInstanceService.getUnit(unitId, import_core3.UniverInstanceType.UNIVER_BASE);
|
|
@@ -1403,9 +1493,9 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1403
1493
|
name: snapshot.name,
|
|
1404
1494
|
unitType: import_core3.UniverInstanceType.UNIVER_BASE
|
|
1405
1495
|
}
|
|
1406
|
-
}, formulaData = { [unitId]: {} };
|
|
1496
|
+
}, formulaData = { [unitId]: {} }, formulaTableNames = (0, import_core3.createBaseFormulaTableNameMap)(snapshot), normalizeFormulaTableReferences = (0, import_core3.createBaseFormulaTableReferenceNormalizer)(snapshot, formulaTableNames);
|
|
1407
1497
|
for (let table of Object.values(snapshot.tables)) {
|
|
1408
|
-
let fieldOrder = table.fieldOrder
|
|
1498
|
+
let fieldOrder = table.fieldOrder;
|
|
1409
1499
|
allUnitData[unitId][table.id] = {
|
|
1410
1500
|
cellData: new import_core3.ObjectMatrix(
|
|
1411
1501
|
buildBaseRuntimeCellData(table)
|
|
@@ -1414,18 +1504,25 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1414
1504
|
columnCount: fieldOrder.length,
|
|
1415
1505
|
rowData: {},
|
|
1416
1506
|
columnData: {}
|
|
1417
|
-
}, unitSheetNameMap[unitId][table.
|
|
1418
|
-
let tableFormulaData = {}, recordOrder = baseRecordOrder(table);
|
|
1507
|
+
}, unitSheetNameMap[unitId][formulaTableNames.get(table.id)] = table.id;
|
|
1508
|
+
let tableFormulaData = {}, normalizedFormulaByFieldId = /* @__PURE__ */ new Map(), recordOrder = baseRecordOrder(table);
|
|
1419
1509
|
for (let row = 0; row < recordOrder.length; row++)
|
|
1420
1510
|
if (table.records[recordOrder[row]])
|
|
1421
1511
|
for (let column = 0; column < fieldOrder.length; column++) {
|
|
1422
1512
|
let field = table.fields[fieldOrder[column]];
|
|
1423
1513
|
if (!field || field.type !== "formula") continue;
|
|
1424
1514
|
let formula = String(field.config?.formula ?? "").trim();
|
|
1425
|
-
|
|
1426
|
-
|
|
1515
|
+
if (!formula) continue;
|
|
1516
|
+
let normalizedFormula = normalizedFormulaByFieldId.get(field.id);
|
|
1517
|
+
normalizedFormula == null && (normalizedFormula = normalizeBaseFormulaForEngine(
|
|
1518
|
+
formula,
|
|
1519
|
+
table,
|
|
1520
|
+
formulaTableNames,
|
|
1521
|
+
normalizeFormulaTableReferences
|
|
1522
|
+
), normalizedFormulaByFieldId.set(field.id, normalizedFormula)), (tableFormulaData[row] ??= {})[column] = {
|
|
1523
|
+
f: normalizedFormula,
|
|
1427
1524
|
si: field.id
|
|
1428
|
-
}
|
|
1525
|
+
};
|
|
1429
1526
|
}
|
|
1430
1527
|
formulaData[unitId][table.id] = tableFormulaData;
|
|
1431
1528
|
}
|
|
@@ -1494,25 +1591,17 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1494
1591
|
_createBaseTableResource(unitId) {
|
|
1495
1592
|
let base = this._univerInstanceService.getUnit(unitId, import_core3.UniverInstanceType.UNIVER_BASE);
|
|
1496
1593
|
if (base) {
|
|
1497
|
-
let snapshot = base.getSnapshot(), tables = Object.values(snapshot.tables), data2 = {};
|
|
1498
|
-
for (let table of tables)
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
for (let name2 of tableNames)
|
|
1594
|
+
let snapshot = base.getSnapshot(), tables = Object.values(snapshot.tables), formulaTableNames = (0, import_core3.createBaseFormulaTableNameMap)(snapshot), data2 = {};
|
|
1595
|
+
for (let table of tables)
|
|
1596
|
+
for (let [name2, reference] of this._getBaseTableEntries(table.id, snapshot, formulaTableNames)) {
|
|
1597
|
+
let columns = Array.from(reference.titleMap.entries()).toSorted((left, right) => left[1] - right[1]).map(([displayName]) => ({ displayName }));
|
|
1502
1598
|
(data2[table.id] ??= { tables: [] }).tables.push({
|
|
1503
1599
|
name: name2,
|
|
1504
|
-
range:
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
startColumn: 0,
|
|
1508
|
-
endColumn: Math.max(0, fieldOrder.length - 1)
|
|
1509
|
-
},
|
|
1510
|
-
columns: fieldOrder.map((fieldId) => ({
|
|
1511
|
-
displayName: table.fields[fieldId]?.name ?? fieldId
|
|
1512
|
-
})),
|
|
1513
|
-
options: { showHeader: !1 }
|
|
1600
|
+
range: reference.range,
|
|
1601
|
+
columns,
|
|
1602
|
+
options: { showHeader: reference.showHeader !== !1 }
|
|
1514
1603
|
});
|
|
1515
|
-
|
|
1604
|
+
}
|
|
1516
1605
|
return [
|
|
1517
1606
|
{
|
|
1518
1607
|
name: "SHEET_TABLE_PLUGIN",
|
|
@@ -1539,6 +1628,22 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1539
1628
|
}
|
|
1540
1629
|
];
|
|
1541
1630
|
}
|
|
1631
|
+
_getBaseTableEntries(tableId, snapshot, formulaTableNames) {
|
|
1632
|
+
let table = snapshot.tables[tableId];
|
|
1633
|
+
if (!table) return [];
|
|
1634
|
+
let recordCount = baseRecordOrder(table).length, fieldOrder = table.fieldOrder, reference = {
|
|
1635
|
+
sheetId: table.id,
|
|
1636
|
+
range: {
|
|
1637
|
+
startRow: 0,
|
|
1638
|
+
endRow: Math.max(0, recordCount - 1),
|
|
1639
|
+
startColumn: 0,
|
|
1640
|
+
endColumn: Math.max(0, fieldOrder.length - 1)
|
|
1641
|
+
},
|
|
1642
|
+
titleMap: new Map(fieldOrder.map((fieldId, index) => [table.fields[fieldId]?.name ?? fieldId, index])),
|
|
1643
|
+
showHeader: !1
|
|
1644
|
+
};
|
|
1645
|
+
return [[formulaTableNames.get(table.id), reference]];
|
|
1646
|
+
}
|
|
1542
1647
|
_rawCellData(cellData) {
|
|
1543
1648
|
let raw = cellData.getMatrix(), result = {};
|
|
1544
1649
|
for (let [row, values] of Object.entries(raw ?? {})) {
|
|
@@ -1549,16 +1654,58 @@ var RustSameRuntimeProjectionController = class extends import_core3.Disposable
|
|
|
1549
1654
|
}
|
|
1550
1655
|
return result;
|
|
1551
1656
|
}
|
|
1552
|
-
}
|
|
1553
|
-
function
|
|
1554
|
-
let
|
|
1555
|
-
return
|
|
1657
|
+
};
|
|
1658
|
+
function createBaseProjectionStructure(snapshot) {
|
|
1659
|
+
let formulaTableNames = (0, import_core3.createBaseFormulaTableNameMap)(snapshot);
|
|
1660
|
+
return {
|
|
1661
|
+
unitName: snapshot.name,
|
|
1662
|
+
tables: Object.fromEntries(
|
|
1663
|
+
Object.values(snapshot.tables).map((table) => [
|
|
1664
|
+
table.id,
|
|
1665
|
+
{
|
|
1666
|
+
formulaName: formulaTableNames.get(table.id),
|
|
1667
|
+
fieldOrder: [...table.fieldOrder],
|
|
1668
|
+
recordOrder: baseRecordOrder(table),
|
|
1669
|
+
fieldSignatures: Object.fromEntries(
|
|
1670
|
+
Object.entries(table.fields).map(([fieldId, field]) => [fieldId, JSON.stringify(field)])
|
|
1671
|
+
)
|
|
1672
|
+
}
|
|
1673
|
+
])
|
|
1674
|
+
)
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
function isSameBaseProjectionStructure(left, right) {
|
|
1678
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
1679
|
+
}
|
|
1680
|
+
function findSingleBaseFieldInsertion(previous, snapshot) {
|
|
1681
|
+
let current = createBaseProjectionStructure(snapshot), previousTableIds = Object.keys(previous.tables).toSorted(), currentTableIds = Object.keys(current.tables).toSorted();
|
|
1682
|
+
if (JSON.stringify(previousTableIds) !== JSON.stringify(currentTableIds)) return null;
|
|
1683
|
+
let insertion = null;
|
|
1684
|
+
for (let tableId of currentTableIds) {
|
|
1685
|
+
let before = previous.tables[tableId], after = current.tables[tableId];
|
|
1686
|
+
if (!before || !after || before.formulaName !== after.formulaName || JSON.stringify(before.recordOrder) !== JSON.stringify(after.recordOrder)) return null;
|
|
1687
|
+
for (let fieldId of before.fieldOrder)
|
|
1688
|
+
if (before.fieldSignatures[fieldId] !== after.fieldSignatures[fieldId]) return null;
|
|
1689
|
+
if (JSON.stringify(before.fieldOrder) === JSON.stringify(after.fieldOrder)) continue;
|
|
1690
|
+
if (insertion || after.fieldOrder.length !== before.fieldOrder.length + 1) return null;
|
|
1691
|
+
let column = after.fieldOrder.findIndex((fieldId, index) => fieldId !== before.fieldOrder[index]);
|
|
1692
|
+
if (column < 0) return null;
|
|
1693
|
+
let withoutInserted = after.fieldOrder.filter((_, index) => index !== column);
|
|
1694
|
+
if (JSON.stringify(withoutInserted) !== JSON.stringify(before.fieldOrder)) return null;
|
|
1695
|
+
insertion = { tableId, column };
|
|
1696
|
+
}
|
|
1697
|
+
return insertion;
|
|
1698
|
+
}
|
|
1699
|
+
var BASE_LEGACY_FIELD_REF_PATTERN = /\{([^}]+)\}/g, BASE_TABLE_REFERENCE_PREFIX = /\b[A-Z_][\w.]*\[/gi, BASE_SCOPED_FIELD_REF_PATTERN = /(^|[^\w[])\[\[\s*#(This Row|Data)\s*\],\s*\[([^\]]+)\]\]/gi, BASE_CURRENT_ROW_FIELD_REF_PATTERN = /(^|[^\w[])\[@\[([^\]]+)\]\](?!\])/g, BASE_BRACKET_FIELD_REF_PATTERN = /(^|[^A-Za-z0-9_[\]])\[([^\]]+)\]/g, BASE_EXTERNAL_A1_REF_PATTERN = /(?:'\[[^\]]+\](?:[^']|'')+'|\[[^\]]+\][^\s'!]+)!\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?/gi, BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX = /(?:'((?:[^']|'')+)'|\[[^\]]+\]|[A-Za-z0-9_.-]+)![^\s![\]]+\[/g;
|
|
1700
|
+
function normalizeBaseFormulaForEngine(formula, currentTable, formulaTableNames, normalizeFormulaTableReferences) {
|
|
1701
|
+
let canonicalFormula = normalizeFormulaTableReferences(formula), references = [], hold = (reference) => `__BASE_FORMULA_REF_${references.push(reference) - 1}__`;
|
|
1702
|
+
return protectBaseTableReferences(protectBaseExternalReferences(canonicalFormula, hold), hold).replace(
|
|
1556
1703
|
BASE_LEGACY_FIELD_REF_PATTERN,
|
|
1557
|
-
(_match, fieldName) => hold(createEngineThisRowRef(currentTable, fieldName,
|
|
1704
|
+
(_match, fieldName) => hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))
|
|
1558
1705
|
).replace(BASE_SCOPED_FIELD_REF_PATTERN, (_match, prefix, scope, fieldName) => {
|
|
1559
|
-
let tableName =
|
|
1706
|
+
let tableName = formulaTableNames.get(currentTable.id) ?? currentTable.name;
|
|
1560
1707
|
return `${prefix}${hold(`${tableName}[[#${scope}],[${fieldName}]]`)}`;
|
|
1561
|
-
}).replace(BASE_CURRENT_ROW_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName,
|
|
1708
|
+
}).replace(BASE_CURRENT_ROW_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(BASE_BRACKET_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(
|
|
1562
1709
|
/__BASE_FORMULA_REF_(\d+)__/g,
|
|
1563
1710
|
(_match, index) => references[Number(index)] ?? ""
|
|
1564
1711
|
);
|
|
@@ -1607,37 +1754,21 @@ function isInsideBaseFormulaString(formula, position) {
|
|
|
1607
1754
|
}
|
|
1608
1755
|
return inString;
|
|
1609
1756
|
}
|
|
1610
|
-
function createEngineThisRowRef(table, fieldName,
|
|
1611
|
-
return `${
|
|
1612
|
-
}
|
|
1613
|
-
function getEngineBaseTableName(table, snapshot) {
|
|
1614
|
-
return isUniqueBaseTableName(table, snapshot) && isExcelTableName(table.name) ? table.name : createStableExcelTableName(table.id);
|
|
1615
|
-
}
|
|
1616
|
-
function isUniqueBaseTableName(table, snapshot) {
|
|
1617
|
-
let normalizedName = table.name.trim().toLowerCase();
|
|
1618
|
-
return Object.values(snapshot.tables).filter((candidate) => candidate.name.trim().toLowerCase() === normalizedName).length === 1;
|
|
1619
|
-
}
|
|
1620
|
-
function isExcelTableName(name2) {
|
|
1621
|
-
return name2.length === 0 || name2.length > 255 || !/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name2) ? !1 : !/^[RC]$/i.test(name2) && !/^[A-Za-z]{1,3}[1-9]\d*$/.test(name2) && !/^R(?:\d+)?C(?:\d+)?$/i.test(name2);
|
|
1622
|
-
}
|
|
1623
|
-
function createStableExcelTableName(tableId) {
|
|
1624
|
-
return `_T_${Array.from(
|
|
1625
|
-
tableId,
|
|
1626
|
-
(character) => /[A-Za-z0-9]/.test(character) ? character : `_x${character.codePointAt(0)?.toString(16) ?? "0"}_`
|
|
1627
|
-
).join("")}`;
|
|
1757
|
+
function createEngineThisRowRef(table, fieldName, formulaTableNames) {
|
|
1758
|
+
return `${formulaTableNames.get(table.id) ?? table.name}[[#This Row],[${fieldName}]]`;
|
|
1628
1759
|
}
|
|
1629
1760
|
function baseRecordOrder(table) {
|
|
1630
1761
|
return table.recordOrder ? table.recordOrder.filter((recordId) => table.records[recordId] != null) : Object.values(table.records ?? {}).toSorted((left, right) => left.orderKey.localeCompare(right.orderKey)).map((record) => record.id);
|
|
1631
1762
|
}
|
|
1632
1763
|
function buildBaseRuntimeCellData(table) {
|
|
1633
|
-
let cellData = { ...table.cellData }, fieldOrder = table.fieldOrder
|
|
1764
|
+
let cellData = { ...table.cellData }, fieldOrder = table.fieldOrder, recordOrder = baseRecordOrder(table);
|
|
1634
1765
|
for (let row = 0; row < recordOrder.length; row++) {
|
|
1635
1766
|
let record = table.records[recordOrder[row]];
|
|
1636
1767
|
if (record) {
|
|
1637
1768
|
cellData[row] = { ...cellData[row] };
|
|
1638
1769
|
for (let column = 0; column < fieldOrder.length; column++) {
|
|
1639
1770
|
let fieldId = fieldOrder[column];
|
|
1640
|
-
Object.prototype.hasOwnProperty.call(record.values ?? {}, fieldId) && (cellData[row][column] = toBaseRuntimeCellData(record.values[fieldId], table.fields[fieldId]));
|
|
1771
|
+
table.fields[fieldId] && Object.prototype.hasOwnProperty.call(record.values ?? {}, fieldId) && (cellData[row][column] = toBaseRuntimeCellData(record.values[fieldId], table.fields[fieldId]));
|
|
1641
1772
|
}
|
|
1642
1773
|
}
|
|
1643
1774
|
}
|
package/lib/es/index.js
CHANGED
|
@@ -179,7 +179,7 @@ import {
|
|
|
179
179
|
CellValueType,
|
|
180
180
|
ObjectMatrix
|
|
181
181
|
} from "@univerjs/core";
|
|
182
|
-
var XLSX_WORKBOOK_CALCULATION_RESOURCE = "UNIVER_CLI_XLSX_WORKBOOK_CALCULATION_PLUGIN", EXTERNAL_DATA_RESOURCE = "SHEET_EXTERNAL_DATA_PLUGIN", EXTERNAL_DATA_SIGNATURE = "external_data", RUST_UPSERT_REFERENCE_DATA_MUTATION_ID = "formula.mutation.upsert-reference-data", RUST_UPSERT_PROJECTION_WORKBOOK_MUTATION_ID = "formula.mutation.upsert-projection-workbook", RUST_FORMULA_RELEVANT_MUTATIONS = /* @__PURE__ */ new Set([
|
|
182
|
+
var XLSX_WORKBOOK_CALCULATION_RESOURCE = "UNIVER_CLI_XLSX_WORKBOOK_CALCULATION_PLUGIN", EXTERNAL_DATA_RESOURCE = "SHEET_EXTERNAL_DATA_PLUGIN", EXTERNAL_DATA_SIGNATURE = "external_data", RUST_UPSERT_REFERENCE_DATA_MUTATION_ID = "formula.mutation.upsert-reference-data", RUST_UPSERT_PROJECTION_WORKBOOK_MUTATION_ID = "formula.mutation.upsert-projection-workbook", RUST_SET_SUPER_TABLES_MUTATION_ID = "formula.mutation.set-super-tables", RUST_FORMULA_RELEVANT_MUTATIONS = /* @__PURE__ */ new Set([
|
|
183
183
|
"sheet.mutation.set-range-values",
|
|
184
184
|
"sheet.mutation.insert-row",
|
|
185
185
|
"sheet.mutation.insert-col",
|
|
@@ -206,6 +206,7 @@ var XLSX_WORKBOOK_CALCULATION_RESOURCE = "UNIVER_CLI_XLSX_WORKBOOK_CALCULATION_P
|
|
|
206
206
|
"formula.mutation.set-image-formula-data",
|
|
207
207
|
"formula.mutation.set-other-formula",
|
|
208
208
|
"formula.mutation.set-super-table",
|
|
209
|
+
RUST_SET_SUPER_TABLES_MUTATION_ID,
|
|
209
210
|
"formula.mutation.set-super-table-option",
|
|
210
211
|
"formula.mutation.remove-defined-name",
|
|
211
212
|
"formula.mutation.remove-feature-calculation",
|
|
@@ -441,13 +442,26 @@ var RustFormulaProjectionService = class {
|
|
|
441
442
|
}
|
|
442
443
|
};
|
|
443
444
|
function normalizeRustEngineMutation(mutation) {
|
|
444
|
-
let params = mutation.id === "formula.mutation.set-super-table" ? normalizeSetSuperTableMutationParams(mutation.params) : mutation.params ?? {};
|
|
445
|
+
let params = mutation.id === "formula.mutation.set-super-table" ? normalizeSetSuperTableMutationParams(mutation.params) : mutation.id === RUST_SET_SUPER_TABLES_MUTATION_ID ? normalizeSetSuperTablesMutationParams(mutation.params) : mutation.params ?? {};
|
|
445
446
|
return {
|
|
446
447
|
id: mutation.id,
|
|
447
448
|
params,
|
|
448
449
|
dirtyRanges: Array.isArray(mutation.dirtyRanges) ? mutation.dirtyRanges : []
|
|
449
450
|
};
|
|
450
451
|
}
|
|
452
|
+
function normalizeSetSuperTablesMutationParams(params) {
|
|
453
|
+
return !isRecord(params) || typeof params.unitId != "string" || !Array.isArray(params.tables) ? params ?? {} : {
|
|
454
|
+
...params,
|
|
455
|
+
tables: params.tables.map((entry) => {
|
|
456
|
+
let normalized = normalizeSetSuperTableMutationParams(
|
|
457
|
+
isRecord(entry) ? { ...entry, unitId: params.unitId } : entry
|
|
458
|
+
);
|
|
459
|
+
if (!isRecord(normalized)) return normalized;
|
|
460
|
+
let { unitId: _unitId, ...table } = normalized;
|
|
461
|
+
return table;
|
|
462
|
+
})
|
|
463
|
+
};
|
|
464
|
+
}
|
|
451
465
|
function normalizeSetSuperTableMutationParams(params) {
|
|
452
466
|
if (!isRecord(params) || !isRecord(params.reference))
|
|
453
467
|
return params ?? {};
|
|
@@ -1015,6 +1029,7 @@ var RustEngineSyncController = class extends Disposable {
|
|
|
1015
1029
|
_nativeReady = !1;
|
|
1016
1030
|
_snapshotLoaded = !1;
|
|
1017
1031
|
_projectionLoadPromise = null;
|
|
1032
|
+
_projectionDeltaBarrier = Promise.resolve();
|
|
1018
1033
|
_pendingMutations = [];
|
|
1019
1034
|
_projectionManagedTableUnits = /* @__PURE__ */ new Set();
|
|
1020
1035
|
_initialize() {
|
|
@@ -1035,6 +1050,13 @@ var RustEngineSyncController = class extends Disposable {
|
|
|
1035
1050
|
}
|
|
1036
1051
|
async waitForProjectionLoad() {
|
|
1037
1052
|
await this._projectionLoadPromise;
|
|
1053
|
+
let barrier;
|
|
1054
|
+
do
|
|
1055
|
+
barrier = this._projectionDeltaBarrier, await barrier;
|
|
1056
|
+
while (barrier !== this._projectionDeltaBarrier);
|
|
1057
|
+
}
|
|
1058
|
+
setProjectionDeltaBarrier(barrier) {
|
|
1059
|
+
this._projectionDeltaBarrier = barrier;
|
|
1038
1060
|
}
|
|
1039
1061
|
async _loadProjection(workbooks) {
|
|
1040
1062
|
await loadNativeBinding(), this._nativeReady = !0;
|
|
@@ -1066,7 +1088,7 @@ var RustEngineSyncController = class extends Disposable {
|
|
|
1066
1088
|
}
|
|
1067
1089
|
}
|
|
1068
1090
|
dispose() {
|
|
1069
|
-
if (super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, !this._nativeReady) {
|
|
1091
|
+
if (super.dispose(), this._pendingMutations.length = 0, this._projectionManagedTableUnits.clear(), this._projectionLoadPromise = null, this._projectionDeltaBarrier = Promise.resolve(), !this._nativeReady) {
|
|
1070
1092
|
this._snapshotLoaded = !1;
|
|
1071
1093
|
return;
|
|
1072
1094
|
}
|
|
@@ -1202,12 +1224,14 @@ import { ICalculateFormulaService } from "@univerjs/engine-formula";
|
|
|
1202
1224
|
import { UniverProFormulaEnginePlugin } from "@univerjs-pro/engine-formula";
|
|
1203
1225
|
|
|
1204
1226
|
// package.json
|
|
1205
|
-
var name = "@univerjs-pro/engine-formula-rust", version = "1.0.0-
|
|
1227
|
+
var name = "@univerjs-pro/engine-formula-rust", version = "1.0.0-rc.0";
|
|
1206
1228
|
|
|
1207
1229
|
// src/controllers/rust-same-runtime-projection.controller.ts
|
|
1208
1230
|
import {
|
|
1209
1231
|
CellValueType as CellValueType2,
|
|
1210
1232
|
CommandType as CommandType2,
|
|
1233
|
+
createBaseFormulaTableReferenceNormalizer,
|
|
1234
|
+
createBaseFormulaTableNameMap,
|
|
1211
1235
|
Disposable as Disposable2,
|
|
1212
1236
|
ICommandService as ICommandService2,
|
|
1213
1237
|
IUniverInstanceService,
|
|
@@ -1242,11 +1266,12 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1242
1266
|
_activeDirtyManagerService;
|
|
1243
1267
|
_initialProjectionLoad = Promise.resolve();
|
|
1244
1268
|
_projectionDeltaQueue = Promise.resolve();
|
|
1269
|
+
_baseProjectionStructures = /* @__PURE__ */ new Map();
|
|
1245
1270
|
_initialize() {
|
|
1246
1271
|
for (let base of this._univerInstanceService.getAllUnitsForType(
|
|
1247
1272
|
UniverInstanceType.UNIVER_BASE
|
|
1248
1273
|
))
|
|
1249
|
-
this._rustEngineSyncController.setProjectionManagedTableUnit(base.getUnitId());
|
|
1274
|
+
this._rustEngineSyncController.setProjectionManagedTableUnit(base.getUnitId()), this._rememberBaseProjectionStructure(base.getSnapshot());
|
|
1250
1275
|
this._initialProjectionLoad = this._loadAllWorkbookProjections(), this.disposeWithMe(
|
|
1251
1276
|
toDisposable(
|
|
1252
1277
|
this._univerInstanceService.getTypeOfUnitAdded$(UniverInstanceType.UNIVER_SHEET).subscribe(({ unit }) => {
|
|
@@ -1261,7 +1286,7 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1261
1286
|
), this.disposeWithMe(
|
|
1262
1287
|
toDisposable(
|
|
1263
1288
|
this._univerInstanceService.getTypeOfUnitAdded$(UniverInstanceType.UNIVER_BASE).subscribe(({ unit }) => {
|
|
1264
|
-
this._rustEngineSyncController.setProjectionManagedTableUnit(unit.getUnitId()), this._enqueueProjectionDelta(() => this._upsertBaseProjection(unit.getUnitId()));
|
|
1289
|
+
this._rustEngineSyncController.setProjectionManagedTableUnit(unit.getUnitId()), this._rememberBaseProjectionStructure(unit.getSnapshot()), this._enqueueProjectionDelta(() => this._upsertBaseProjection(unit.getUnitId()));
|
|
1265
1290
|
})
|
|
1266
1291
|
)
|
|
1267
1292
|
), this.disposeWithMe(
|
|
@@ -1271,7 +1296,7 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1271
1296
|
), this.disposeWithMe(
|
|
1272
1297
|
toDisposable(
|
|
1273
1298
|
this._univerInstanceService.getTypeOfUnitDisposed$(UniverInstanceType.UNIVER_BASE).subscribe((base) => {
|
|
1274
|
-
this._rustEngineSyncController.unsetProjectionManagedTableUnit(base.getUnitId()), this._enqueueProjectionDelta(
|
|
1299
|
+
this._baseProjectionStructures.delete(base.getUnitId()), this._rustEngineSyncController.unsetProjectionManagedTableUnit(base.getUnitId()), this._enqueueProjectionDelta(
|
|
1275
1300
|
() => this._rustEngineSyncController.disposeProjectionWorkbook(base.getUnitId())
|
|
1276
1301
|
);
|
|
1277
1302
|
})
|
|
@@ -1295,7 +1320,7 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1295
1320
|
if (!this._disposed)
|
|
1296
1321
|
return task();
|
|
1297
1322
|
}).catch(() => {
|
|
1298
|
-
});
|
|
1323
|
+
}), this._rustEngineSyncController.setProjectionDeltaBarrier(this._projectionDeltaQueue);
|
|
1299
1324
|
}
|
|
1300
1325
|
async _syncBaseMutation(command) {
|
|
1301
1326
|
if (!hasUnitId2(command.params)) return;
|
|
@@ -1304,7 +1329,65 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1304
1329
|
this._applyBaseDirtyRanges(unitId, dirtyRanges);
|
|
1305
1330
|
return;
|
|
1306
1331
|
}
|
|
1307
|
-
await this._upsertBaseProjection(unitId);
|
|
1332
|
+
hasStructureInvalidation && this._isBaseProjectionStructureUnchanged(unitId) || hasStructureInvalidation && this._applyBaseFieldInsertion(unitId, dirtyRanges) || await this._upsertBaseProjection(unitId);
|
|
1333
|
+
}
|
|
1334
|
+
_applyBaseFieldInsertion(unitId, dirtyRanges) {
|
|
1335
|
+
let base = this._univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_BASE), previous = this._baseProjectionStructures.get(unitId);
|
|
1336
|
+
if (!base || !previous) return !1;
|
|
1337
|
+
let snapshot = base.getSnapshot(), insertion = findSingleBaseFieldInsertion(previous, snapshot);
|
|
1338
|
+
if (!insertion) return !1;
|
|
1339
|
+
let projectionData = this._getBaseProjectionData(unitId), sheet = projectionData?.calculationData.allUnitData[unitId]?.[insertion.tableId];
|
|
1340
|
+
if (!projectionData || !sheet) return !1;
|
|
1341
|
+
let formulaData = projectionData.formulaData[unitId]?.[insertion.tableId], cellValue = {};
|
|
1342
|
+
for (let row = 0; row < sheet.rowCount; row++) {
|
|
1343
|
+
let value = sheet.cellData.getValue(row, insertion.column), formula = formulaData?.[row]?.[insertion.column];
|
|
1344
|
+
cellValue[row] = {
|
|
1345
|
+
[insertion.column]: formula ? { ...value, ...formula } : value ?? null
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
let insertedRange = {
|
|
1349
|
+
startRow: 0,
|
|
1350
|
+
endRow: Math.max(0, sheet.rowCount - 1),
|
|
1351
|
+
startColumn: insertion.column,
|
|
1352
|
+
endColumn: insertion.column
|
|
1353
|
+
};
|
|
1354
|
+
return this._rustEngineSyncController.applyProjectionMutation({
|
|
1355
|
+
id: "sheet.mutation.insert-col",
|
|
1356
|
+
params: {
|
|
1357
|
+
unitId,
|
|
1358
|
+
subUnitId: insertion.tableId,
|
|
1359
|
+
range: insertedRange
|
|
1360
|
+
},
|
|
1361
|
+
dirtyRanges: []
|
|
1362
|
+
}), this._rustEngineSyncController.applyProjectionMutation({
|
|
1363
|
+
id: "sheet.mutation.set-range-values",
|
|
1364
|
+
params: {
|
|
1365
|
+
unitId,
|
|
1366
|
+
subUnitId: insertion.tableId,
|
|
1367
|
+
cellValue
|
|
1368
|
+
},
|
|
1369
|
+
dirtyRanges: [
|
|
1370
|
+
{
|
|
1371
|
+
unitId,
|
|
1372
|
+
sheetId: insertion.tableId,
|
|
1373
|
+
range: insertedRange
|
|
1374
|
+
}
|
|
1375
|
+
]
|
|
1376
|
+
}), this._rustEngineSyncController.applyProjectionMutation({
|
|
1377
|
+
id: RUST_SET_SUPER_TABLES_MUTATION_ID,
|
|
1378
|
+
params: {
|
|
1379
|
+
unitId,
|
|
1380
|
+
tables: this._getBaseTableEntries(
|
|
1381
|
+
insertion.tableId,
|
|
1382
|
+
snapshot,
|
|
1383
|
+
createBaseFormulaTableNameMap(snapshot)
|
|
1384
|
+
).map(([tableName, reference]) => ({
|
|
1385
|
+
tableName,
|
|
1386
|
+
reference
|
|
1387
|
+
}))
|
|
1388
|
+
},
|
|
1389
|
+
dirtyRanges: []
|
|
1390
|
+
}), dirtyRanges.length > 0 && this._applyBaseDirtyRanges(unitId, dirtyRanges), this._rememberBaseProjectionStructure(snapshot), !0;
|
|
1308
1391
|
}
|
|
1309
1392
|
_applyBaseDirtyRanges(unitId, dirtyRanges) {
|
|
1310
1393
|
let projectionData = this._getBaseProjectionData(unitId);
|
|
@@ -1346,6 +1429,15 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1346
1429
|
formulaData
|
|
1347
1430
|
);
|
|
1348
1431
|
workbook && this._rustEngineSyncController.upsertProjectionWorkbook(workbook);
|
|
1432
|
+
let base = this._univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_BASE);
|
|
1433
|
+
base && this._rememberBaseProjectionStructure(base.getSnapshot());
|
|
1434
|
+
}
|
|
1435
|
+
_rememberBaseProjectionStructure(snapshot) {
|
|
1436
|
+
this._baseProjectionStructures.set(snapshot.id, createBaseProjectionStructure(snapshot));
|
|
1437
|
+
}
|
|
1438
|
+
_isBaseProjectionStructureUnchanged(unitId) {
|
|
1439
|
+
let base = this._univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_BASE), previous = this._baseProjectionStructures.get(unitId);
|
|
1440
|
+
return !!(base && previous && isSameBaseProjectionStructure(previous, createBaseProjectionStructure(base.getSnapshot())));
|
|
1349
1441
|
}
|
|
1350
1442
|
_getBaseProjectionData(unitId) {
|
|
1351
1443
|
let base = this._univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_BASE);
|
|
@@ -1355,9 +1447,9 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1355
1447
|
name: snapshot.name,
|
|
1356
1448
|
unitType: UniverInstanceType.UNIVER_BASE
|
|
1357
1449
|
}
|
|
1358
|
-
}, formulaData = { [unitId]: {} };
|
|
1450
|
+
}, formulaData = { [unitId]: {} }, formulaTableNames = createBaseFormulaTableNameMap(snapshot), normalizeFormulaTableReferences = createBaseFormulaTableReferenceNormalizer(snapshot, formulaTableNames);
|
|
1359
1451
|
for (let table of Object.values(snapshot.tables)) {
|
|
1360
|
-
let fieldOrder = table.fieldOrder
|
|
1452
|
+
let fieldOrder = table.fieldOrder;
|
|
1361
1453
|
allUnitData[unitId][table.id] = {
|
|
1362
1454
|
cellData: new ObjectMatrix2(
|
|
1363
1455
|
buildBaseRuntimeCellData(table)
|
|
@@ -1366,18 +1458,25 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1366
1458
|
columnCount: fieldOrder.length,
|
|
1367
1459
|
rowData: {},
|
|
1368
1460
|
columnData: {}
|
|
1369
|
-
}, unitSheetNameMap[unitId][table.
|
|
1370
|
-
let tableFormulaData = {}, recordOrder = baseRecordOrder(table);
|
|
1461
|
+
}, unitSheetNameMap[unitId][formulaTableNames.get(table.id)] = table.id;
|
|
1462
|
+
let tableFormulaData = {}, normalizedFormulaByFieldId = /* @__PURE__ */ new Map(), recordOrder = baseRecordOrder(table);
|
|
1371
1463
|
for (let row = 0; row < recordOrder.length; row++)
|
|
1372
1464
|
if (table.records[recordOrder[row]])
|
|
1373
1465
|
for (let column = 0; column < fieldOrder.length; column++) {
|
|
1374
1466
|
let field = table.fields[fieldOrder[column]];
|
|
1375
1467
|
if (!field || field.type !== "formula") continue;
|
|
1376
1468
|
let formula = String(field.config?.formula ?? "").trim();
|
|
1377
|
-
|
|
1378
|
-
|
|
1469
|
+
if (!formula) continue;
|
|
1470
|
+
let normalizedFormula = normalizedFormulaByFieldId.get(field.id);
|
|
1471
|
+
normalizedFormula == null && (normalizedFormula = normalizeBaseFormulaForEngine(
|
|
1472
|
+
formula,
|
|
1473
|
+
table,
|
|
1474
|
+
formulaTableNames,
|
|
1475
|
+
normalizeFormulaTableReferences
|
|
1476
|
+
), normalizedFormulaByFieldId.set(field.id, normalizedFormula)), (tableFormulaData[row] ??= {})[column] = {
|
|
1477
|
+
f: normalizedFormula,
|
|
1379
1478
|
si: field.id
|
|
1380
|
-
}
|
|
1479
|
+
};
|
|
1381
1480
|
}
|
|
1382
1481
|
formulaData[unitId][table.id] = tableFormulaData;
|
|
1383
1482
|
}
|
|
@@ -1446,25 +1545,17 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1446
1545
|
_createBaseTableResource(unitId) {
|
|
1447
1546
|
let base = this._univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_BASE);
|
|
1448
1547
|
if (base) {
|
|
1449
|
-
let snapshot = base.getSnapshot(), tables = Object.values(snapshot.tables), data2 = {};
|
|
1450
|
-
for (let table of tables)
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
for (let name2 of tableNames)
|
|
1548
|
+
let snapshot = base.getSnapshot(), tables = Object.values(snapshot.tables), formulaTableNames = createBaseFormulaTableNameMap(snapshot), data2 = {};
|
|
1549
|
+
for (let table of tables)
|
|
1550
|
+
for (let [name2, reference] of this._getBaseTableEntries(table.id, snapshot, formulaTableNames)) {
|
|
1551
|
+
let columns = Array.from(reference.titleMap.entries()).toSorted((left, right) => left[1] - right[1]).map(([displayName]) => ({ displayName }));
|
|
1454
1552
|
(data2[table.id] ??= { tables: [] }).tables.push({
|
|
1455
1553
|
name: name2,
|
|
1456
|
-
range:
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
startColumn: 0,
|
|
1460
|
-
endColumn: Math.max(0, fieldOrder.length - 1)
|
|
1461
|
-
},
|
|
1462
|
-
columns: fieldOrder.map((fieldId) => ({
|
|
1463
|
-
displayName: table.fields[fieldId]?.name ?? fieldId
|
|
1464
|
-
})),
|
|
1465
|
-
options: { showHeader: !1 }
|
|
1554
|
+
range: reference.range,
|
|
1555
|
+
columns,
|
|
1556
|
+
options: { showHeader: reference.showHeader !== !1 }
|
|
1466
1557
|
});
|
|
1467
|
-
|
|
1558
|
+
}
|
|
1468
1559
|
return [
|
|
1469
1560
|
{
|
|
1470
1561
|
name: "SHEET_TABLE_PLUGIN",
|
|
@@ -1491,6 +1582,22 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1491
1582
|
}
|
|
1492
1583
|
];
|
|
1493
1584
|
}
|
|
1585
|
+
_getBaseTableEntries(tableId, snapshot, formulaTableNames) {
|
|
1586
|
+
let table = snapshot.tables[tableId];
|
|
1587
|
+
if (!table) return [];
|
|
1588
|
+
let recordCount = baseRecordOrder(table).length, fieldOrder = table.fieldOrder, reference = {
|
|
1589
|
+
sheetId: table.id,
|
|
1590
|
+
range: {
|
|
1591
|
+
startRow: 0,
|
|
1592
|
+
endRow: Math.max(0, recordCount - 1),
|
|
1593
|
+
startColumn: 0,
|
|
1594
|
+
endColumn: Math.max(0, fieldOrder.length - 1)
|
|
1595
|
+
},
|
|
1596
|
+
titleMap: new Map(fieldOrder.map((fieldId, index) => [table.fields[fieldId]?.name ?? fieldId, index])),
|
|
1597
|
+
showHeader: !1
|
|
1598
|
+
};
|
|
1599
|
+
return [[formulaTableNames.get(table.id), reference]];
|
|
1600
|
+
}
|
|
1494
1601
|
_rawCellData(cellData) {
|
|
1495
1602
|
let raw = cellData.getMatrix(), result = {};
|
|
1496
1603
|
for (let [row, values] of Object.entries(raw ?? {})) {
|
|
@@ -1501,16 +1608,58 @@ var RustSameRuntimeProjectionController = class extends Disposable2 {
|
|
|
1501
1608
|
}
|
|
1502
1609
|
return result;
|
|
1503
1610
|
}
|
|
1504
|
-
}
|
|
1505
|
-
function
|
|
1506
|
-
let
|
|
1507
|
-
return
|
|
1611
|
+
};
|
|
1612
|
+
function createBaseProjectionStructure(snapshot) {
|
|
1613
|
+
let formulaTableNames = createBaseFormulaTableNameMap(snapshot);
|
|
1614
|
+
return {
|
|
1615
|
+
unitName: snapshot.name,
|
|
1616
|
+
tables: Object.fromEntries(
|
|
1617
|
+
Object.values(snapshot.tables).map((table) => [
|
|
1618
|
+
table.id,
|
|
1619
|
+
{
|
|
1620
|
+
formulaName: formulaTableNames.get(table.id),
|
|
1621
|
+
fieldOrder: [...table.fieldOrder],
|
|
1622
|
+
recordOrder: baseRecordOrder(table),
|
|
1623
|
+
fieldSignatures: Object.fromEntries(
|
|
1624
|
+
Object.entries(table.fields).map(([fieldId, field]) => [fieldId, JSON.stringify(field)])
|
|
1625
|
+
)
|
|
1626
|
+
}
|
|
1627
|
+
])
|
|
1628
|
+
)
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
function isSameBaseProjectionStructure(left, right) {
|
|
1632
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
1633
|
+
}
|
|
1634
|
+
function findSingleBaseFieldInsertion(previous, snapshot) {
|
|
1635
|
+
let current = createBaseProjectionStructure(snapshot), previousTableIds = Object.keys(previous.tables).toSorted(), currentTableIds = Object.keys(current.tables).toSorted();
|
|
1636
|
+
if (JSON.stringify(previousTableIds) !== JSON.stringify(currentTableIds)) return null;
|
|
1637
|
+
let insertion = null;
|
|
1638
|
+
for (let tableId of currentTableIds) {
|
|
1639
|
+
let before = previous.tables[tableId], after = current.tables[tableId];
|
|
1640
|
+
if (!before || !after || before.formulaName !== after.formulaName || JSON.stringify(before.recordOrder) !== JSON.stringify(after.recordOrder)) return null;
|
|
1641
|
+
for (let fieldId of before.fieldOrder)
|
|
1642
|
+
if (before.fieldSignatures[fieldId] !== after.fieldSignatures[fieldId]) return null;
|
|
1643
|
+
if (JSON.stringify(before.fieldOrder) === JSON.stringify(after.fieldOrder)) continue;
|
|
1644
|
+
if (insertion || after.fieldOrder.length !== before.fieldOrder.length + 1) return null;
|
|
1645
|
+
let column = after.fieldOrder.findIndex((fieldId, index) => fieldId !== before.fieldOrder[index]);
|
|
1646
|
+
if (column < 0) return null;
|
|
1647
|
+
let withoutInserted = after.fieldOrder.filter((_, index) => index !== column);
|
|
1648
|
+
if (JSON.stringify(withoutInserted) !== JSON.stringify(before.fieldOrder)) return null;
|
|
1649
|
+
insertion = { tableId, column };
|
|
1650
|
+
}
|
|
1651
|
+
return insertion;
|
|
1652
|
+
}
|
|
1653
|
+
var BASE_LEGACY_FIELD_REF_PATTERN = /\{([^}]+)\}/g, BASE_TABLE_REFERENCE_PREFIX = /\b[A-Z_][\w.]*\[/gi, BASE_SCOPED_FIELD_REF_PATTERN = /(^|[^\w[])\[\[\s*#(This Row|Data)\s*\],\s*\[([^\]]+)\]\]/gi, BASE_CURRENT_ROW_FIELD_REF_PATTERN = /(^|[^\w[])\[@\[([^\]]+)\]\](?!\])/g, BASE_BRACKET_FIELD_REF_PATTERN = /(^|[^A-Za-z0-9_[\]])\[([^\]]+)\]/g, BASE_EXTERNAL_A1_REF_PATTERN = /(?:'\[[^\]]+\](?:[^']|'')+'|\[[^\]]+\][^\s'!]+)!\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?/gi, BASE_EXTERNAL_STRUCTURED_REFERENCE_PREFIX = /(?:'((?:[^']|'')+)'|\[[^\]]+\]|[A-Za-z0-9_.-]+)![^\s![\]]+\[/g;
|
|
1654
|
+
function normalizeBaseFormulaForEngine(formula, currentTable, formulaTableNames, normalizeFormulaTableReferences) {
|
|
1655
|
+
let canonicalFormula = normalizeFormulaTableReferences(formula), references = [], hold = (reference) => `__BASE_FORMULA_REF_${references.push(reference) - 1}__`;
|
|
1656
|
+
return protectBaseTableReferences(protectBaseExternalReferences(canonicalFormula, hold), hold).replace(
|
|
1508
1657
|
BASE_LEGACY_FIELD_REF_PATTERN,
|
|
1509
|
-
(_match, fieldName) => hold(createEngineThisRowRef(currentTable, fieldName,
|
|
1658
|
+
(_match, fieldName) => hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))
|
|
1510
1659
|
).replace(BASE_SCOPED_FIELD_REF_PATTERN, (_match, prefix, scope, fieldName) => {
|
|
1511
|
-
let tableName =
|
|
1660
|
+
let tableName = formulaTableNames.get(currentTable.id) ?? currentTable.name;
|
|
1512
1661
|
return `${prefix}${hold(`${tableName}[[#${scope}],[${fieldName}]]`)}`;
|
|
1513
|
-
}).replace(BASE_CURRENT_ROW_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName,
|
|
1662
|
+
}).replace(BASE_CURRENT_ROW_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(BASE_BRACKET_FIELD_REF_PATTERN, (_match, prefix, fieldName) => `${prefix}${hold(createEngineThisRowRef(currentTable, fieldName, formulaTableNames))}`).replace(
|
|
1514
1663
|
/__BASE_FORMULA_REF_(\d+)__/g,
|
|
1515
1664
|
(_match, index) => references[Number(index)] ?? ""
|
|
1516
1665
|
);
|
|
@@ -1559,37 +1708,21 @@ function isInsideBaseFormulaString(formula, position) {
|
|
|
1559
1708
|
}
|
|
1560
1709
|
return inString;
|
|
1561
1710
|
}
|
|
1562
|
-
function createEngineThisRowRef(table, fieldName,
|
|
1563
|
-
return `${
|
|
1564
|
-
}
|
|
1565
|
-
function getEngineBaseTableName(table, snapshot) {
|
|
1566
|
-
return isUniqueBaseTableName(table, snapshot) && isExcelTableName(table.name) ? table.name : createStableExcelTableName(table.id);
|
|
1567
|
-
}
|
|
1568
|
-
function isUniqueBaseTableName(table, snapshot) {
|
|
1569
|
-
let normalizedName = table.name.trim().toLowerCase();
|
|
1570
|
-
return Object.values(snapshot.tables).filter((candidate) => candidate.name.trim().toLowerCase() === normalizedName).length === 1;
|
|
1571
|
-
}
|
|
1572
|
-
function isExcelTableName(name2) {
|
|
1573
|
-
return name2.length === 0 || name2.length > 255 || !/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name2) ? !1 : !/^[RC]$/i.test(name2) && !/^[A-Za-z]{1,3}[1-9]\d*$/.test(name2) && !/^R(?:\d+)?C(?:\d+)?$/i.test(name2);
|
|
1574
|
-
}
|
|
1575
|
-
function createStableExcelTableName(tableId) {
|
|
1576
|
-
return `_T_${Array.from(
|
|
1577
|
-
tableId,
|
|
1578
|
-
(character) => /[A-Za-z0-9]/.test(character) ? character : `_x${character.codePointAt(0)?.toString(16) ?? "0"}_`
|
|
1579
|
-
).join("")}`;
|
|
1711
|
+
function createEngineThisRowRef(table, fieldName, formulaTableNames) {
|
|
1712
|
+
return `${formulaTableNames.get(table.id) ?? table.name}[[#This Row],[${fieldName}]]`;
|
|
1580
1713
|
}
|
|
1581
1714
|
function baseRecordOrder(table) {
|
|
1582
1715
|
return table.recordOrder ? table.recordOrder.filter((recordId) => table.records[recordId] != null) : Object.values(table.records ?? {}).toSorted((left, right) => left.orderKey.localeCompare(right.orderKey)).map((record) => record.id);
|
|
1583
1716
|
}
|
|
1584
1717
|
function buildBaseRuntimeCellData(table) {
|
|
1585
|
-
let cellData = { ...table.cellData }, fieldOrder = table.fieldOrder
|
|
1718
|
+
let cellData = { ...table.cellData }, fieldOrder = table.fieldOrder, recordOrder = baseRecordOrder(table);
|
|
1586
1719
|
for (let row = 0; row < recordOrder.length; row++) {
|
|
1587
1720
|
let record = table.records[recordOrder[row]];
|
|
1588
1721
|
if (record) {
|
|
1589
1722
|
cellData[row] = { ...cellData[row] };
|
|
1590
1723
|
for (let column = 0; column < fieldOrder.length; column++) {
|
|
1591
1724
|
let fieldId = fieldOrder[column];
|
|
1592
|
-
Object.prototype.hasOwnProperty.call(record.values ?? {}, fieldId) && (cellData[row][column] = toBaseRuntimeCellData(record.values[fieldId], table.fields[fieldId]));
|
|
1725
|
+
table.fields[fieldId] && Object.prototype.hasOwnProperty.call(record.values ?? {}, fieldId) && (cellData[row][column] = toBaseRuntimeCellData(record.values[fieldId], table.fields[fieldId]));
|
|
1593
1726
|
}
|
|
1594
1727
|
}
|
|
1595
1728
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -587,12 +587,14 @@ declare class RustEngineSyncController extends Disposable {
|
|
|
587
587
|
private _nativeReady;
|
|
588
588
|
private _snapshotLoaded;
|
|
589
589
|
private _projectionLoadPromise;
|
|
590
|
+
private _projectionDeltaBarrier;
|
|
590
591
|
private readonly _pendingMutations;
|
|
591
592
|
private readonly _projectionManagedTableUnits;
|
|
592
593
|
constructor(_commandService: ICommandService);
|
|
593
594
|
private _initialize;
|
|
594
595
|
loadProjection(workbooks: readonly IRustProjectionWorkbookInput[]): Promise<void>;
|
|
595
596
|
waitForProjectionLoad(): Promise<void>;
|
|
597
|
+
setProjectionDeltaBarrier(barrier: Promise<void>): void;
|
|
596
598
|
private _loadProjection;
|
|
597
599
|
applyProjectionMutation(mutation: IRustEngineMutation): void;
|
|
598
600
|
upsertProjectionWorkbook(workbook: IRustProjectionWorkbookInput): void;
|
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-insiders.
|
|
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.0-rc.0",
|
|
5
|
+
"@univerjs-pro/engine-formula-rust-binding": "1.0.0-insiders.20260910-22fe9c7",
|
|
6
|
+
"@univerjs/core": "1.0.0-rc.0",
|
|
7
|
+
"@univerjs/engine-formula": "1.0.0-rc.0",
|
|
8
|
+
"@univerjs/protocol": "1.0.0-rc.0"
|
|
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.0-rc.0",
|
|
24
24
|
"main": "./lib/cjs/index.cjs",
|
|
25
25
|
"module": "./lib/es/index.js",
|
|
26
26
|
"types": "./lib/types/index.d.ts",
|