@bilig/headless 0.2.0 → 0.3.1
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/dist/fast-range-read.d.ts +4 -0
- package/dist/fast-range-read.js +81 -0
- package/dist/fast-range-read.js.map +1 -0
- package/dist/initial-sheet-load.d.ts +11 -5
- package/dist/initial-sheet-load.js +168 -65
- package/dist/initial-sheet-load.js.map +1 -1
- package/dist/tracked-cell-index-changes.d.ts +32 -6
- package/dist/tracked-cell-index-changes.js +635 -4
- package/dist/tracked-cell-index-changes.js.map +1 -1
- package/dist/tracked-engine-event-refs.d.ts +9 -1
- package/dist/tracked-engine-event-refs.js +152 -8
- package/dist/tracked-engine-event-refs.js.map +1 -1
- package/dist/work-paper-runtime.d.ts +29 -0
- package/dist/work-paper-runtime.js +1146 -106
- package/dist/work-paper-runtime.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,20 +1,37 @@
|
|
|
1
1
|
import { indexToColumn } from '@bilig/formula';
|
|
2
|
-
import {
|
|
2
|
+
import { makeCellKey } from '@bilig/core';
|
|
3
|
+
import { ErrorCode, ValueTag } from '@bilig/protocol';
|
|
4
|
+
const COLUMN_LABEL_CACHE = [];
|
|
5
|
+
const DEFERRED_TRACKED_INDEX_CHANGES = new WeakMap();
|
|
6
|
+
const LAZY_PUBLIC_CHANGE_SOURCE_THRESHOLD = 256;
|
|
3
7
|
export function materializeTrackedIndexChangesWithMetadata(engine, changedCellIndices, options = {}) {
|
|
4
8
|
if (changedCellIndices.length === 0) {
|
|
5
9
|
return { changes: [], ordered: true };
|
|
6
10
|
}
|
|
7
11
|
const workbook = engine.workbook;
|
|
8
12
|
const cellStore = workbook.cellStore;
|
|
9
|
-
const columnLabels = [];
|
|
10
13
|
const formatAddressCached = (row, col) => {
|
|
11
|
-
let label =
|
|
14
|
+
let label = COLUMN_LABEL_CACHE[col];
|
|
12
15
|
if (label === undefined) {
|
|
13
16
|
label = indexToColumn(col);
|
|
14
|
-
|
|
17
|
+
COLUMN_LABEL_CACHE[col] = label;
|
|
15
18
|
}
|
|
16
19
|
return `${label}${row + 1}`;
|
|
17
20
|
};
|
|
21
|
+
if (options.lazy && options.trustedPhysicalSheetId !== undefined) {
|
|
22
|
+
const sheet = workbook.getSheetById(options.trustedPhysicalSheetId);
|
|
23
|
+
if (!sheet || sheet.structureVersion === 1) {
|
|
24
|
+
const split = options.trustedSortedSliceSplit !== undefined &&
|
|
25
|
+
options.trustedSortedSliceSplit > 0 &&
|
|
26
|
+
options.trustedSortedSliceSplit < changedCellIndices.length
|
|
27
|
+
? options.trustedSortedSliceSplit
|
|
28
|
+
: undefined;
|
|
29
|
+
return {
|
|
30
|
+
changes: createLazyPhysicalTrackedIndexChanges(options.trustedPhysicalSheetId, sheet?.name ?? workbook.getSheetNameById(options.trustedPhysicalSheetId), cellStore, engine, changedCellIndices, formatAddressCached, split),
|
|
31
|
+
ordered: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
18
35
|
let firstSheetId;
|
|
19
36
|
for (let index = 0; index < changedCellIndices.length; index += 1) {
|
|
20
37
|
const sheetId = cellStore.sheetIds[changedCellIndices[index]];
|
|
@@ -26,6 +43,14 @@ export function materializeTrackedIndexChangesWithMetadata(engine, changedCellIn
|
|
|
26
43
|
if (firstSheetId === undefined) {
|
|
27
44
|
return { changes: [], ordered: true };
|
|
28
45
|
}
|
|
46
|
+
if (options.lazy) {
|
|
47
|
+
const lazyPhysicalChanges = tryCreateLazyPhysicalTrackedIndexChanges(engine, changedCellIndices, firstSheetId, formatAddressCached, {
|
|
48
|
+
sortedSliceSplit: options.explicitChangedCount,
|
|
49
|
+
});
|
|
50
|
+
if (lazyPhysicalChanges) {
|
|
51
|
+
return { changes: lazyPhysicalChanges, ordered: true };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
29
54
|
let isSingleSheetChangeSet = true;
|
|
30
55
|
for (let index = 0; index < changedCellIndices.length; index += 1) {
|
|
31
56
|
const sheetId = cellStore.sheetIds[changedCellIndices[index]];
|
|
@@ -46,6 +71,12 @@ export function materializeTrackedIndexChangesWithMetadata(engine, changedCellIn
|
|
|
46
71
|
split < changedCellIndices.length &&
|
|
47
72
|
isTrackedIndexSliceSorted(cellStore, changedCellIndices, 0, split) &&
|
|
48
73
|
isTrackedIndexSliceSorted(cellStore, changedCellIndices, split, changedCellIndices.length)) {
|
|
74
|
+
if (options.lazy && trackedIndicesAllBelongToSheet(cellStore, changedCellIndices, firstSheetId)) {
|
|
75
|
+
return {
|
|
76
|
+
changes: createLazyPhysicalTrackedIndexChanges(firstSheetId, sheetName, cellStore, engine, changedCellIndices, formatAddressCached, split),
|
|
77
|
+
ordered: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
49
80
|
let explicitIndex = 0;
|
|
50
81
|
let recalculatedIndex = split;
|
|
51
82
|
while (explicitIndex < split && recalculatedIndex < changedCellIndices.length) {
|
|
@@ -70,6 +101,15 @@ export function materializeTrackedIndexChangesWithMetadata(engine, changedCellIn
|
|
|
70
101
|
}
|
|
71
102
|
return { changes, ordered: true };
|
|
72
103
|
}
|
|
104
|
+
if (options.lazy &&
|
|
105
|
+
isPhysicalSheet &&
|
|
106
|
+
trackedIndicesAllBelongToSheet(cellStore, changedCellIndices, firstSheetId) &&
|
|
107
|
+
isTrackedIndexSliceSorted(cellStore, changedCellIndices, 0, changedCellIndices.length)) {
|
|
108
|
+
return {
|
|
109
|
+
changes: createLazyPhysicalTrackedIndexChanges(firstSheetId, sheetName, cellStore, engine, changedCellIndices, formatAddressCached),
|
|
110
|
+
ordered: true,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
73
113
|
let ordered = true;
|
|
74
114
|
let previousRow = -1;
|
|
75
115
|
let previousCol = -1;
|
|
@@ -169,6 +209,108 @@ export function materializeTrackedIndexChangesWithMetadata(engine, changedCellIn
|
|
|
169
209
|
export function materializeTrackedIndexChanges(engine, changedCellIndices, options = {}) {
|
|
170
210
|
return materializeTrackedIndexChangesWithMetadata(engine, changedCellIndices, options).changes;
|
|
171
211
|
}
|
|
212
|
+
export function materializeTrackedIndexChangeSourcesWithMetadata(engine, sources, options = {}) {
|
|
213
|
+
if (sources.length === 0) {
|
|
214
|
+
return { changes: [], ordered: true, usedSortedDisjointFastPath: true };
|
|
215
|
+
}
|
|
216
|
+
for (const source of sources) {
|
|
217
|
+
if (source.invalidation === 'full' ||
|
|
218
|
+
(source.patches !== undefined && source.patches.length > 0) ||
|
|
219
|
+
source.hasInvalidatedRanges ||
|
|
220
|
+
source.hasInvalidatedRows ||
|
|
221
|
+
source.hasInvalidatedColumns) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const lazySameSheetChanges = tryCreateLazySameSheetTrackedSourceChanges(engine, sources, {
|
|
226
|
+
deferLazyDetach: options.deferLazyDetach === true,
|
|
227
|
+
preferLazyPublicChanges: options.lazy === true,
|
|
228
|
+
});
|
|
229
|
+
if (lazySameSheetChanges) {
|
|
230
|
+
return lazySameSheetChanges;
|
|
231
|
+
}
|
|
232
|
+
if (sources.length === 1) {
|
|
233
|
+
const materialized = materializeTrackedIndexChangesWithMetadata(engine, sources[0].changedCellIndices, {
|
|
234
|
+
...options,
|
|
235
|
+
explicitChangedCount: sources[0].explicitChangedCount,
|
|
236
|
+
});
|
|
237
|
+
return {
|
|
238
|
+
changes: materialized.changes,
|
|
239
|
+
ordered: materialized.ordered,
|
|
240
|
+
usedSortedDisjointFastPath: materialized.ordered && trackedSourceHasSortedDisjointIndices(sources[0]),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const materializedSources = Array.from({ length: sources.length }, () => undefined);
|
|
244
|
+
const sheetOrders = sheetOrderLookup(engine);
|
|
245
|
+
const fastChanges = [];
|
|
246
|
+
let previousNumericCellIndex = -1;
|
|
247
|
+
let previousPublicChange;
|
|
248
|
+
let canUseSortedDisjointFastPath = true;
|
|
249
|
+
for (let sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
|
|
250
|
+
const source = sources[sourceIndex];
|
|
251
|
+
if (!trackedSourceHasSortedDisjointIndices(source)) {
|
|
252
|
+
canUseSortedDisjointFastPath = false;
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
if (source.changedCellIndices.length > 0) {
|
|
256
|
+
const first = source.firstChangedCellIndex ?? source.changedCellIndices[0];
|
|
257
|
+
const last = source.lastChangedCellIndex ?? source.changedCellIndices[source.changedCellIndices.length - 1];
|
|
258
|
+
if (first <= previousNumericCellIndex) {
|
|
259
|
+
canUseSortedDisjointFastPath = false;
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
previousNumericCellIndex = last;
|
|
263
|
+
}
|
|
264
|
+
const materialized = materializeTrackedIndexChangesWithMetadata(engine, source.changedCellIndices, {
|
|
265
|
+
...options,
|
|
266
|
+
explicitChangedCount: source.explicitChangedCount,
|
|
267
|
+
});
|
|
268
|
+
materializedSources[sourceIndex] = materialized;
|
|
269
|
+
if (!materialized.ordered) {
|
|
270
|
+
canUseSortedDisjointFastPath = false;
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
for (let changeIndex = 0; changeIndex < materialized.changes.length; changeIndex += 1) {
|
|
274
|
+
const change = materialized.changes[changeIndex];
|
|
275
|
+
if (previousPublicChange !== undefined) {
|
|
276
|
+
const comparison = compareTrackedCellChanges(previousPublicChange, change, sheetOrders);
|
|
277
|
+
if (comparison >= 0) {
|
|
278
|
+
canUseSortedDisjointFastPath = false;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
fastChanges.push(change);
|
|
283
|
+
previousPublicChange = change;
|
|
284
|
+
}
|
|
285
|
+
if (!canUseSortedDisjointFastPath) {
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (canUseSortedDisjointFastPath) {
|
|
290
|
+
return { changes: fastChanges, ordered: true, usedSortedDisjointFastPath: true };
|
|
291
|
+
}
|
|
292
|
+
return materializeTrackedIndexChangeSourcesGeneric(engine, sources, materializedSources, options, sheetOrders);
|
|
293
|
+
}
|
|
294
|
+
export function forceMaterializeTrackedIndexChanges(changes) {
|
|
295
|
+
const deferred = DEFERRED_TRACKED_INDEX_CHANGES.get(changes);
|
|
296
|
+
if (deferred === undefined) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
deferred.forceMaterialize();
|
|
300
|
+
DEFERRED_TRACKED_INDEX_CHANGES.delete(changes);
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
export function detachTrackedIndexChanges(changes, options = {}) {
|
|
304
|
+
const deferred = DEFERRED_TRACKED_INDEX_CHANGES.get(changes);
|
|
305
|
+
if (deferred === undefined) {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
deferred.detach(options);
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
export function hasDeferredTrackedIndexChanges(changes) {
|
|
312
|
+
return DEFERRED_TRACKED_INDEX_CHANGES.has(changes);
|
|
313
|
+
}
|
|
172
314
|
function readTrackedCellValue(cellStore, cellIndex, engine) {
|
|
173
315
|
const tag = cellStore.tags[cellIndex] ?? ValueTag.Empty;
|
|
174
316
|
switch (tag) {
|
|
@@ -185,6 +327,183 @@ function readTrackedCellValue(cellStore, cellIndex, engine) {
|
|
|
185
327
|
return { tag: ValueTag.Empty };
|
|
186
328
|
}
|
|
187
329
|
}
|
|
330
|
+
function materializeTrackedIndexChangeSourcesGeneric(engine, sources, materializedSources, options, sheetOrders) {
|
|
331
|
+
const latestChangesByKey = new Map();
|
|
332
|
+
for (let sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
|
|
333
|
+
const source = sources[sourceIndex];
|
|
334
|
+
const materialized = materializedSources[sourceIndex] ??
|
|
335
|
+
materializeTrackedIndexChangesWithMetadata(engine, source.changedCellIndices, {
|
|
336
|
+
...options,
|
|
337
|
+
explicitChangedCount: source.explicitChangedCount,
|
|
338
|
+
});
|
|
339
|
+
for (let changeIndex = 0; changeIndex < materialized.changes.length; changeIndex += 1) {
|
|
340
|
+
const change = materialized.changes[changeIndex];
|
|
341
|
+
const key = makeCellKey(change.address.sheet, change.address.row, change.address.col);
|
|
342
|
+
latestChangesByKey.delete(key);
|
|
343
|
+
latestChangesByKey.set(key, change);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
changes: orderTrackedCellChanges([...latestChangesByKey.values()], sheetOrders),
|
|
348
|
+
ordered: true,
|
|
349
|
+
usedSortedDisjointFastPath: false,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function tryCreateLazySameSheetTrackedSourceChanges(engine, sources, options) {
|
|
353
|
+
let totalLength = 0;
|
|
354
|
+
for (let sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
|
|
355
|
+
totalLength += sources[sourceIndex].changedCellIndices.length;
|
|
356
|
+
}
|
|
357
|
+
if (!options.preferLazyPublicChanges && totalLength < LAZY_PUBLIC_CHANGE_SOURCE_THRESHOLD) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
const workbook = engine.workbook;
|
|
361
|
+
const cellStore = workbook.cellStore;
|
|
362
|
+
const orderedSources = [];
|
|
363
|
+
let sheetId;
|
|
364
|
+
let previousNumericCellIndex = -1;
|
|
365
|
+
let previousLastCellIndex;
|
|
366
|
+
for (let sourceIndex = 0; sourceIndex < sources.length; sourceIndex += 1) {
|
|
367
|
+
const source = sources[sourceIndex];
|
|
368
|
+
if (!trackedSourceHasSortedDisjointIndices(source)) {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
if (source.changedCellIndices.length === 0) {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const firstNumericCellIndex = source.firstChangedCellIndex ?? source.changedCellIndices[0];
|
|
375
|
+
const lastNumericCellIndex = source.lastChangedCellIndex ?? source.changedCellIndices[source.changedCellIndices.length - 1];
|
|
376
|
+
if (firstNumericCellIndex <= previousNumericCellIndex) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
previousNumericCellIndex = lastNumericCellIndex;
|
|
380
|
+
const sourceSheetId = cellStore.sheetIds[source.changedCellIndices[0]];
|
|
381
|
+
if (sourceSheetId === undefined) {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
if (sheetId === undefined) {
|
|
385
|
+
sheetId = sourceSheetId;
|
|
386
|
+
}
|
|
387
|
+
else if (sourceSheetId !== sheetId) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
const sheet = workbook.getSheetById(sourceSheetId);
|
|
391
|
+
if (sheet && sheet.structureVersion !== 1) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
if (!trackedIndicesAllBelongToSheet(cellStore, source.changedCellIndices, sourceSheetId)) {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
const orderedSource = orderedTrackedIndexSource(cellStore, source);
|
|
398
|
+
if (orderedSource === null) {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
if (previousLastCellIndex !== undefined &&
|
|
402
|
+
compareTrackedPhysicalCellIndices(cellStore, previousLastCellIndex, orderedSource.firstCellIndex) >= 0) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
previousLastCellIndex = orderedSource.lastCellIndex;
|
|
406
|
+
orderedSources.push(orderedSource);
|
|
407
|
+
}
|
|
408
|
+
if (sheetId === undefined) {
|
|
409
|
+
return { changes: [], ordered: true, usedSortedDisjointFastPath: true };
|
|
410
|
+
}
|
|
411
|
+
const orderedCellIndices = new Uint32Array(totalLength);
|
|
412
|
+
let offset = 0;
|
|
413
|
+
for (let sourceIndex = 0; sourceIndex < orderedSources.length; sourceIndex += 1) {
|
|
414
|
+
const source = orderedSources[sourceIndex];
|
|
415
|
+
offset = copyOrderedTrackedCellIndices(cellStore, source.changedCellIndices, orderedCellIndices, offset, source.sortedSliceSplit);
|
|
416
|
+
}
|
|
417
|
+
const sheet = workbook.getSheetById(sheetId);
|
|
418
|
+
const sheetName = sheet?.name ?? workbook.getSheetNameById(sheetId);
|
|
419
|
+
const changes = createLazyPhysicalTrackedIndexChanges(sheetId, sheetName, cellStore, engine, orderedCellIndices, formatTrackedAddress);
|
|
420
|
+
if (!options.deferLazyDetach) {
|
|
421
|
+
detachTrackedIndexChanges(changes);
|
|
422
|
+
}
|
|
423
|
+
return { changes, ordered: true, usedSortedDisjointFastPath: true };
|
|
424
|
+
}
|
|
425
|
+
function orderedTrackedIndexSource(cellStore, source) {
|
|
426
|
+
const length = source.changedCellIndices.length;
|
|
427
|
+
const split = source.explicitChangedCount;
|
|
428
|
+
if (split !== undefined && split > 0 && split < length) {
|
|
429
|
+
if (!isTrackedIndexSliceSorted(cellStore, source.changedCellIndices, 0, split) ||
|
|
430
|
+
!isTrackedIndexSliceSorted(cellStore, source.changedCellIndices, split, length)) {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
const firstLeft = source.changedCellIndices[0];
|
|
434
|
+
const firstRight = source.changedCellIndices[split];
|
|
435
|
+
const lastLeft = source.changedCellIndices[split - 1];
|
|
436
|
+
const lastRight = source.changedCellIndices[length - 1];
|
|
437
|
+
return {
|
|
438
|
+
changedCellIndices: source.changedCellIndices,
|
|
439
|
+
sortedSliceSplit: split,
|
|
440
|
+
firstCellIndex: compareTrackedPhysicalCellIndices(cellStore, firstLeft, firstRight) <= 0 ? firstLeft : firstRight,
|
|
441
|
+
lastCellIndex: compareTrackedPhysicalCellIndices(cellStore, lastLeft, lastRight) >= 0 ? lastLeft : lastRight,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
if (!isTrackedIndexSliceSorted(cellStore, source.changedCellIndices, 0, length)) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
changedCellIndices: source.changedCellIndices,
|
|
449
|
+
firstCellIndex: source.changedCellIndices[0],
|
|
450
|
+
lastCellIndex: source.changedCellIndices[length - 1],
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function trackedSourceHasSortedDisjointIndices(source) {
|
|
454
|
+
if (source.changedCellIndicesSortedDisjoint !== undefined) {
|
|
455
|
+
return source.changedCellIndicesSortedDisjoint;
|
|
456
|
+
}
|
|
457
|
+
let previous = -1;
|
|
458
|
+
for (let index = 0; index < source.changedCellIndices.length; index += 1) {
|
|
459
|
+
const cellIndex = source.changedCellIndices[index];
|
|
460
|
+
if (!Number.isInteger(cellIndex) || cellIndex < 0 || cellIndex <= previous) {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
previous = cellIndex;
|
|
464
|
+
}
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
function sheetOrderLookup(engine) {
|
|
468
|
+
const sheetOrders = new Map();
|
|
469
|
+
engine.workbook.sheetsById.forEach((sheet, sheetId) => {
|
|
470
|
+
sheetOrders.set(sheetId, sheet.order);
|
|
471
|
+
});
|
|
472
|
+
return sheetOrders;
|
|
473
|
+
}
|
|
474
|
+
function compareTrackedCellChanges(left, right, sheetOrders) {
|
|
475
|
+
return ((sheetOrders.get(left.address.sheet) ?? 0) - (sheetOrders.get(right.address.sheet) ?? 0) ||
|
|
476
|
+
left.address.row - right.address.row ||
|
|
477
|
+
left.address.col - right.address.col);
|
|
478
|
+
}
|
|
479
|
+
function orderTrackedCellChanges(changes, sheetOrders) {
|
|
480
|
+
if (changes.length < 2) {
|
|
481
|
+
return changes;
|
|
482
|
+
}
|
|
483
|
+
if (isTrackedCellChangeSliceSorted(changes, sheetOrders, 0, changes.length)) {
|
|
484
|
+
return changes;
|
|
485
|
+
}
|
|
486
|
+
if (isTrackedCellChangeSliceReverseSorted(changes, sheetOrders, 0, changes.length)) {
|
|
487
|
+
return changes.toReversed();
|
|
488
|
+
}
|
|
489
|
+
return changes.toSorted((left, right) => compareTrackedCellChanges(left, right, sheetOrders));
|
|
490
|
+
}
|
|
491
|
+
function isTrackedCellChangeSliceSorted(changes, sheetOrders, start, end) {
|
|
492
|
+
for (let index = start + 1; index < end; index += 1) {
|
|
493
|
+
if (compareTrackedCellChanges(changes[index - 1], changes[index], sheetOrders) > 0) {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
function isTrackedCellChangeSliceReverseSorted(changes, sheetOrders, start, end) {
|
|
500
|
+
for (let index = start + 1; index < end; index += 1) {
|
|
501
|
+
if (compareTrackedCellChanges(changes[index - 1], changes[index], sheetOrders) < 0) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
188
507
|
function compareTrackedPhysicalCellIndices(cellStore, leftCellIndex, rightCellIndex) {
|
|
189
508
|
return ((cellStore.rows[leftCellIndex] ?? 0) - (cellStore.rows[rightCellIndex] ?? 0) ||
|
|
190
509
|
(cellStore.cols[leftCellIndex] ?? 0) - (cellStore.cols[rightCellIndex] ?? 0));
|
|
@@ -197,6 +516,14 @@ function isTrackedIndexSliceSorted(cellStore, changedCellIndices, start, end) {
|
|
|
197
516
|
}
|
|
198
517
|
return true;
|
|
199
518
|
}
|
|
519
|
+
function formatTrackedAddress(row, col) {
|
|
520
|
+
let label = COLUMN_LABEL_CACHE[col];
|
|
521
|
+
if (label === undefined) {
|
|
522
|
+
label = indexToColumn(col);
|
|
523
|
+
COLUMN_LABEL_CACHE[col] = label;
|
|
524
|
+
}
|
|
525
|
+
return `${label}${row + 1}`;
|
|
526
|
+
}
|
|
200
527
|
function readPhysicalTrackedIndexChange(cellIndex, sheetId, sheetName, cellStore, engine, formatAddressCached) {
|
|
201
528
|
const row = cellStore.rows[cellIndex];
|
|
202
529
|
const col = cellStore.cols[cellIndex];
|
|
@@ -208,4 +535,308 @@ function readPhysicalTrackedIndexChange(cellIndex, sheetId, sheetName, cellStore
|
|
|
208
535
|
newValue: readTrackedCellValue(cellStore, cellIndex, engine),
|
|
209
536
|
};
|
|
210
537
|
}
|
|
538
|
+
function trackedIndicesAllBelongToSheet(cellStore, changedCellIndices, sheetId) {
|
|
539
|
+
for (let index = 0; index < changedCellIndices.length; index += 1) {
|
|
540
|
+
if (cellStore.sheetIds[changedCellIndices[index]] !== sheetId) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
function createLazyPhysicalTrackedIndexChanges(sheetId, sheetName, cellStore, engine, changedCellIndices, formatAddressCached, sortedSliceSplit) {
|
|
547
|
+
const changedCellIndicesForMaterialization = changedCellIndices instanceof Uint32Array ? changedCellIndices : copyTrackedCellIndices(changedCellIndices);
|
|
548
|
+
const length = changedCellIndicesForMaterialization.length;
|
|
549
|
+
const cache = [];
|
|
550
|
+
cache.length = length;
|
|
551
|
+
let detached;
|
|
552
|
+
let fullyMaterialized = false;
|
|
553
|
+
let orderedCellIndices;
|
|
554
|
+
const hasMaterializedIndex = (index) => Object.prototype.hasOwnProperty.call(cache, index);
|
|
555
|
+
const orderedCellIndexAt = (index) => {
|
|
556
|
+
if (sortedSliceSplit === undefined) {
|
|
557
|
+
return changedCellIndicesForMaterialization[index];
|
|
558
|
+
}
|
|
559
|
+
if (orderedCellIndices === undefined) {
|
|
560
|
+
orderedCellIndices = new Uint32Array(length);
|
|
561
|
+
copyOrderedTrackedCellIndices(cellStore, changedCellIndicesForMaterialization, orderedCellIndices, 0, sortedSliceSplit);
|
|
562
|
+
}
|
|
563
|
+
return orderedCellIndices[index];
|
|
564
|
+
};
|
|
565
|
+
const forEachOrderedCellIndex = (fn) => {
|
|
566
|
+
if (sortedSliceSplit === undefined) {
|
|
567
|
+
for (let index = 0; index < length; index += 1) {
|
|
568
|
+
fn(index, changedCellIndicesForMaterialization[index]);
|
|
569
|
+
}
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (orderedCellIndices === undefined) {
|
|
573
|
+
orderedCellIndices = new Uint32Array(length);
|
|
574
|
+
copyOrderedTrackedCellIndices(cellStore, changedCellIndicesForMaterialization, orderedCellIndices, 0, sortedSliceSplit);
|
|
575
|
+
}
|
|
576
|
+
for (let index = 0; index < length; index += 1) {
|
|
577
|
+
fn(index, orderedCellIndices[index]);
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
const materialize = (index) => {
|
|
581
|
+
if (hasMaterializedIndex(index)) {
|
|
582
|
+
return cache[index];
|
|
583
|
+
}
|
|
584
|
+
if (detached) {
|
|
585
|
+
cache[index] = readDetachedPhysicalTrackedIndexChange(index, sheetId, sheetName, cellStore, detached, formatAddressCached);
|
|
586
|
+
return cache[index];
|
|
587
|
+
}
|
|
588
|
+
cache[index] = readPhysicalTrackedIndexChange(orderedCellIndexAt(index), sheetId, sheetName, cellStore, engine, formatAddressCached);
|
|
589
|
+
return cache[index];
|
|
590
|
+
};
|
|
591
|
+
const detach = (options = {}) => {
|
|
592
|
+
if (fullyMaterialized) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const preservePositions = options.preservePositions ?? true;
|
|
596
|
+
if (detached !== undefined) {
|
|
597
|
+
if (preservePositions && detached.rows === undefined) {
|
|
598
|
+
if (detached.cellIndices === undefined) {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const rows = new Uint32Array(length);
|
|
602
|
+
const cols = new Uint32Array(length);
|
|
603
|
+
for (let index = 0; index < length; index += 1) {
|
|
604
|
+
const cellIndex = detached.cellIndices[index];
|
|
605
|
+
rows[index] = cellStore.rows[cellIndex] ?? 0;
|
|
606
|
+
cols[index] = cellStore.cols[cellIndex] ?? 0;
|
|
607
|
+
}
|
|
608
|
+
detached = { ...detached, rows, cols };
|
|
609
|
+
}
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
const cellIndices = preservePositions ? undefined : new Uint32Array(length);
|
|
613
|
+
const rows = preservePositions ? new Uint32Array(length) : undefined;
|
|
614
|
+
const cols = preservePositions ? new Uint32Array(length) : undefined;
|
|
615
|
+
const numbers = new Float64Array(length);
|
|
616
|
+
let tags;
|
|
617
|
+
let constantTag;
|
|
618
|
+
let errors;
|
|
619
|
+
let stringIds;
|
|
620
|
+
let strings;
|
|
621
|
+
const ensureTags = (currentIndex) => {
|
|
622
|
+
if (tags !== undefined) {
|
|
623
|
+
return tags;
|
|
624
|
+
}
|
|
625
|
+
const nextTags = new Uint8Array(length);
|
|
626
|
+
nextTags.fill(constantTag ?? ValueTag.Empty, 0, currentIndex);
|
|
627
|
+
tags = nextTags;
|
|
628
|
+
return nextTags;
|
|
629
|
+
};
|
|
630
|
+
forEachOrderedCellIndex((index, cellIndex) => {
|
|
631
|
+
if (cellIndices !== undefined) {
|
|
632
|
+
cellIndices[index] = cellIndex;
|
|
633
|
+
}
|
|
634
|
+
if (rows !== undefined && cols !== undefined) {
|
|
635
|
+
rows[index] = cellStore.rows[cellIndex] ?? 0;
|
|
636
|
+
cols[index] = cellStore.cols[cellIndex] ?? 0;
|
|
637
|
+
}
|
|
638
|
+
const tag = cellStore.tags[cellIndex] ?? ValueTag.Empty;
|
|
639
|
+
if (tags !== undefined) {
|
|
640
|
+
tags[index] = tag;
|
|
641
|
+
}
|
|
642
|
+
else if (constantTag === undefined) {
|
|
643
|
+
constantTag = tag;
|
|
644
|
+
}
|
|
645
|
+
else if (tag !== constantTag) {
|
|
646
|
+
ensureTags(index)[index] = tag;
|
|
647
|
+
}
|
|
648
|
+
switch (tag) {
|
|
649
|
+
case ValueTag.Number:
|
|
650
|
+
case ValueTag.Boolean:
|
|
651
|
+
numbers[index] = cellStore.numbers[cellIndex] ?? 0;
|
|
652
|
+
break;
|
|
653
|
+
case ValueTag.String:
|
|
654
|
+
{
|
|
655
|
+
stringIds ??= new Int32Array(length);
|
|
656
|
+
strings ??= [];
|
|
657
|
+
stringIds[index] = cellStore.stringIds[cellIndex] ?? 0;
|
|
658
|
+
const value = cellStore.getValue(cellIndex, (stringId) => engine.strings.get(stringId));
|
|
659
|
+
strings[index] = value.tag === ValueTag.String ? value.value : '';
|
|
660
|
+
}
|
|
661
|
+
break;
|
|
662
|
+
case ValueTag.Error:
|
|
663
|
+
errors ??= new Int32Array(length);
|
|
664
|
+
errors[index] = cellStore.errors[cellIndex] ?? ErrorCode.None;
|
|
665
|
+
break;
|
|
666
|
+
case ValueTag.Empty:
|
|
667
|
+
default:
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
detached = {
|
|
672
|
+
...(cellIndices === undefined ? {} : { cellIndices }),
|
|
673
|
+
...(rows !== undefined && cols !== undefined ? { rows, cols } : {}),
|
|
674
|
+
...(tags !== undefined ? { tags } : { constantTag: constantTag ?? ValueTag.Empty }),
|
|
675
|
+
numbers,
|
|
676
|
+
...(errors === undefined ? {} : { errors }),
|
|
677
|
+
...(stringIds === undefined ? {} : { stringIds }),
|
|
678
|
+
...(strings === undefined ? {} : { strings }),
|
|
679
|
+
};
|
|
680
|
+
};
|
|
681
|
+
const forceMaterialize = () => {
|
|
682
|
+
if (fullyMaterialized) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
if (detached !== undefined) {
|
|
686
|
+
for (let index = 0; index < length; index += 1) {
|
|
687
|
+
if (!hasMaterializedIndex(index)) {
|
|
688
|
+
cache[index] = readDetachedPhysicalTrackedIndexChange(index, sheetId, sheetName, cellStore, detached, formatAddressCached);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
fullyMaterialized = true;
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
for (let index = 0; index < length; index += 1) {
|
|
695
|
+
if (!hasMaterializedIndex(index)) {
|
|
696
|
+
cache[index] = readPhysicalTrackedIndexChange(orderedCellIndexAt(index), sheetId, sheetName, cellStore, engine, formatAddressCached);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
fullyMaterialized = true;
|
|
700
|
+
};
|
|
701
|
+
const numericIndexOf = (property) => {
|
|
702
|
+
if (typeof property !== 'string' || property.length === 0) {
|
|
703
|
+
return undefined;
|
|
704
|
+
}
|
|
705
|
+
const index = Number(property);
|
|
706
|
+
return Number.isInteger(index) && index >= 0 && index < length && String(index) === property ? index : undefined;
|
|
707
|
+
};
|
|
708
|
+
const proxy = new Proxy(cache, {
|
|
709
|
+
get(target, property, receiver) {
|
|
710
|
+
const index = numericIndexOf(property);
|
|
711
|
+
return index === undefined ? Reflect.get(target, property, receiver) : materialize(index);
|
|
712
|
+
},
|
|
713
|
+
getOwnPropertyDescriptor(target, property) {
|
|
714
|
+
const index = numericIndexOf(property);
|
|
715
|
+
if (index === undefined) {
|
|
716
|
+
return Reflect.getOwnPropertyDescriptor(target, property);
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
configurable: true,
|
|
720
|
+
enumerable: true,
|
|
721
|
+
value: materialize(index),
|
|
722
|
+
writable: true,
|
|
723
|
+
};
|
|
724
|
+
},
|
|
725
|
+
has(target, property) {
|
|
726
|
+
return numericIndexOf(property) !== undefined || Reflect.has(target, property);
|
|
727
|
+
},
|
|
728
|
+
ownKeys(target) {
|
|
729
|
+
return [
|
|
730
|
+
...Array.from({ length }, (_value, index) => String(index)),
|
|
731
|
+
...Reflect.ownKeys(target).filter((key) => typeof key !== 'string' || numericIndexOf(key) === undefined),
|
|
732
|
+
];
|
|
733
|
+
},
|
|
734
|
+
});
|
|
735
|
+
DEFERRED_TRACKED_INDEX_CHANGES.set(proxy, { forceMaterialize, detach });
|
|
736
|
+
return proxy;
|
|
737
|
+
}
|
|
738
|
+
function tryCreateLazyPhysicalTrackedIndexChanges(engine, changedCellIndices, sheetId, formatAddressCached, options = {}) {
|
|
739
|
+
const workbook = engine.workbook;
|
|
740
|
+
const sheet = workbook.getSheetById(sheetId);
|
|
741
|
+
if (sheet && sheet.structureVersion !== 1) {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
const cellStore = workbook.cellStore;
|
|
745
|
+
const length = changedCellIndices.length;
|
|
746
|
+
const split = options.sortedSliceSplit;
|
|
747
|
+
const sortedSliceSplit = split !== undefined && split > 0 && split < length ? split : undefined;
|
|
748
|
+
let previousRow = -1;
|
|
749
|
+
let previousCol = -1;
|
|
750
|
+
let previousRightRow = -1;
|
|
751
|
+
let previousRightCol = -1;
|
|
752
|
+
for (let index = 0; index < length; index += 1) {
|
|
753
|
+
const cellIndex = changedCellIndices[index];
|
|
754
|
+
if (cellStore.sheetIds[cellIndex] !== sheetId) {
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
const row = cellStore.rows[cellIndex] ?? 0;
|
|
758
|
+
const col = cellStore.cols[cellIndex] ?? 0;
|
|
759
|
+
if (sortedSliceSplit !== undefined && index >= sortedSliceSplit) {
|
|
760
|
+
if (row < previousRightRow || (row === previousRightRow && col < previousRightCol)) {
|
|
761
|
+
return null;
|
|
762
|
+
}
|
|
763
|
+
previousRightRow = row;
|
|
764
|
+
previousRightCol = col;
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
if (row < previousRow || (row === previousRow && col < previousCol)) {
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
770
|
+
previousRow = row;
|
|
771
|
+
previousCol = col;
|
|
772
|
+
}
|
|
773
|
+
const sheetName = sheet?.name ?? workbook.getSheetNameById(sheetId);
|
|
774
|
+
return createLazyPhysicalTrackedIndexChanges(sheetId, sheetName, cellStore, engine, changedCellIndices, formatAddressCached, sortedSliceSplit);
|
|
775
|
+
}
|
|
776
|
+
function copyOrderedTrackedCellIndices(cellStore, changedCellIndices, target, offset, sortedSliceSplit) {
|
|
777
|
+
if (sortedSliceSplit === undefined) {
|
|
778
|
+
for (let index = 0; index < changedCellIndices.length; index += 1) {
|
|
779
|
+
target[offset + index] = changedCellIndices[index];
|
|
780
|
+
}
|
|
781
|
+
return offset + changedCellIndices.length;
|
|
782
|
+
}
|
|
783
|
+
let explicitIndex = 0;
|
|
784
|
+
let recalculatedIndex = sortedSliceSplit;
|
|
785
|
+
let outputIndex = offset;
|
|
786
|
+
while (explicitIndex < sortedSliceSplit && recalculatedIndex < changedCellIndices.length) {
|
|
787
|
+
const explicitCellIndex = changedCellIndices[explicitIndex];
|
|
788
|
+
const recalculatedCellIndex = changedCellIndices[recalculatedIndex];
|
|
789
|
+
if (compareTrackedPhysicalCellIndices(cellStore, explicitCellIndex, recalculatedCellIndex) <= 0) {
|
|
790
|
+
target[outputIndex] = explicitCellIndex;
|
|
791
|
+
explicitIndex += 1;
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
target[outputIndex] = recalculatedCellIndex;
|
|
795
|
+
recalculatedIndex += 1;
|
|
796
|
+
}
|
|
797
|
+
outputIndex += 1;
|
|
798
|
+
}
|
|
799
|
+
while (explicitIndex < sortedSliceSplit) {
|
|
800
|
+
target[outputIndex] = changedCellIndices[explicitIndex];
|
|
801
|
+
explicitIndex += 1;
|
|
802
|
+
outputIndex += 1;
|
|
803
|
+
}
|
|
804
|
+
while (recalculatedIndex < changedCellIndices.length) {
|
|
805
|
+
target[outputIndex] = changedCellIndices[recalculatedIndex];
|
|
806
|
+
recalculatedIndex += 1;
|
|
807
|
+
outputIndex += 1;
|
|
808
|
+
}
|
|
809
|
+
return outputIndex;
|
|
810
|
+
}
|
|
811
|
+
function copyTrackedCellIndices(changedCellIndices) {
|
|
812
|
+
return Uint32Array.from(changedCellIndices);
|
|
813
|
+
}
|
|
814
|
+
function readDetachedPhysicalTrackedIndexChange(index, sheetId, sheetName, cellStore, detached, formatAddressCached) {
|
|
815
|
+
const cellIndex = detached.cellIndices?.[index];
|
|
816
|
+
const row = detached.rows?.[index] ?? (cellIndex === undefined ? 0 : (cellStore.rows[cellIndex] ?? 0));
|
|
817
|
+
const col = detached.cols?.[index] ?? (cellIndex === undefined ? 0 : (cellStore.cols[cellIndex] ?? 0));
|
|
818
|
+
return {
|
|
819
|
+
kind: 'cell',
|
|
820
|
+
address: { sheet: sheetId, row, col },
|
|
821
|
+
sheetName,
|
|
822
|
+
a1: formatAddressCached(row, col),
|
|
823
|
+
newValue: readDetachedCellValue(detached, index),
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
function readDetachedCellValue(detached, index) {
|
|
827
|
+
const tag = (detached.tags?.[index] ?? detached.constantTag ?? ValueTag.Empty);
|
|
828
|
+
switch (tag) {
|
|
829
|
+
case ValueTag.Number:
|
|
830
|
+
return { tag: ValueTag.Number, value: detached.numbers[index] ?? 0 };
|
|
831
|
+
case ValueTag.Boolean:
|
|
832
|
+
return { tag: ValueTag.Boolean, value: (detached.numbers[index] ?? 0) !== 0 };
|
|
833
|
+
case ValueTag.String:
|
|
834
|
+
return { tag: ValueTag.String, value: detached.strings?.[index] ?? '', stringId: detached.stringIds?.[index] ?? 0 };
|
|
835
|
+
case ValueTag.Error:
|
|
836
|
+
return { tag: ValueTag.Error, code: detached.errors?.[index] ?? ErrorCode.None };
|
|
837
|
+
case ValueTag.Empty:
|
|
838
|
+
default:
|
|
839
|
+
return { tag: ValueTag.Empty };
|
|
840
|
+
}
|
|
841
|
+
}
|
|
211
842
|
//# sourceMappingURL=tracked-cell-index-changes.js.map
|