@rowsncolumns/y-spreadsheet 15.0.0 → 15.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/dist/cjs/helpers.d.ts.map +1 -1
- package/dist/cjs/helpers.js +178 -194
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/helpers.d.ts.map +1 -1
- package/dist/esm/helpers.js +104 -123
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +14 -11
- package/dist/cjs/profiling/batch-profile.spec.d.ts +0 -2
- package/dist/cjs/profiling/batch-profile.spec.d.ts.map +0 -1
- package/dist/cjs/profiling/batch-profile.spec.js +0 -175
- package/dist/esm/profiling/batch-profile.spec.d.ts +0 -2
- package/dist/esm/profiling/batch-profile.spec.d.ts.map +0 -1
- package/dist/esm/profiling/batch-profile.spec.js +0 -131
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,KAAK,EAEX,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,iCAAiC,CAAC;AAWzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAOzB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAEV,SAAS,EACT,UAAU,EACV,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;QACjC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;IACJ,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,CAAC,CAAC,GAAG,EACV,QAAQ,MAAM,GAAG,MAAM,EACvB,SAAS,CACP,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAC9B,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CACtC,EAAE,EACH,SAAS,OAAO,GAAG,MAAM,GAAG,SAAS,EACrC,mBAAmB,IAAI,GAAG,IAAI,SAyG/B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAC7B,SAAS,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/helpers.js
CHANGED
|
@@ -132,127 +132,81 @@ exports.applyPatchesToYDoc = applyPatchesToYDoc;
|
|
|
132
132
|
* 2. Grouping updates by sheet/row for efficient batch application
|
|
133
133
|
*/
|
|
134
134
|
var addSheetDataPatches = function (ySheetData, patches) {
|
|
135
|
-
var e_2, _a
|
|
136
|
-
// Optimization:
|
|
137
|
-
//
|
|
135
|
+
var e_2, _a;
|
|
136
|
+
// Optimization: consecutive cell-level patches are consolidated (later
|
|
137
|
+
// patches override earlier ones for the same cell) and applied together,
|
|
138
|
+
// grouped by sheet and row so bulk operations like paste (10k+ rows) cost
|
|
139
|
+
// one row lookup per row. They are never reordered ACROSS a row- or
|
|
140
|
+
// sheet-level patch (see `addSheetDataPatchesV3`).
|
|
138
141
|
// Key format: "sheetId:rowIndex:columnIndex"
|
|
139
|
-
var
|
|
140
|
-
var
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
// Use string representation for sheet ID to handle both string and numeric IDs
|
|
153
|
-
var sheetIdStr = String(sheetIdRaw);
|
|
154
|
-
if (op === "replace" || op === "add") {
|
|
155
|
-
// [sheetId, rowIndex, 'values', columnIndex] - Single cell update (most common in paste)
|
|
156
|
-
if (path.length === 4) {
|
|
157
|
-
var _g = tslib_1.__read(path, 4), rowIndex = _g[1], columnIndex = _g[3];
|
|
158
|
-
var rowIdx = Number(rowIndex);
|
|
159
|
-
var colIdx = Number(columnIndex);
|
|
160
|
-
var key = "".concat(sheetIdStr, ":").concat(rowIdx, ":").concat(colIdx);
|
|
161
|
-
// Later patches override earlier ones for the same cell
|
|
162
|
-
cellUpdates.set(key, { sheetIdStr: sheetIdStr, rowIdx: rowIdx, colIdx: colIdx, value: value });
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
// Row-level or sheet-level updates
|
|
166
|
-
otherPatches.push(patch);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else if (op === "remove") {
|
|
170
|
-
if (path.length === 4) {
|
|
171
|
-
var _h = tslib_1.__read(path, 4), rowIndex = _h[1], columnIndex = _h[3];
|
|
172
|
-
var rowIdx = Number(rowIndex);
|
|
173
|
-
var colIdx = Number(columnIndex);
|
|
174
|
-
var key = "".concat(sheetIdStr, ":").concat(rowIdx, ":").concat(colIdx);
|
|
175
|
-
cellUpdates.set(key, { sheetIdStr: sheetIdStr, rowIdx: rowIdx, colIdx: colIdx, value: null });
|
|
142
|
+
var pendingCellUpdates = new Map();
|
|
143
|
+
var flushPendingCellUpdates = function () {
|
|
144
|
+
var e_3, _a, e_4, _b, e_5, _c, e_6, _d;
|
|
145
|
+
if (pendingCellUpdates.size === 0) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
var sheetRowUpdates = new Map();
|
|
149
|
+
try {
|
|
150
|
+
for (var pendingCellUpdates_1 = tslib_1.__values(pendingCellUpdates), pendingCellUpdates_1_1 = pendingCellUpdates_1.next(); !pendingCellUpdates_1_1.done; pendingCellUpdates_1_1 = pendingCellUpdates_1.next()) {
|
|
151
|
+
var _e = tslib_1.__read(pendingCellUpdates_1_1.value, 2), _f = _e[1], sheetIdStr = _f.sheetIdStr, rowIdx = _f.rowIdx, colIdx = _f.colIdx, value = _f.value;
|
|
152
|
+
if (!sheetRowUpdates.has(sheetIdStr)) {
|
|
153
|
+
sheetRowUpdates.set(sheetIdStr, new Map());
|
|
176
154
|
}
|
|
177
|
-
|
|
178
|
-
|
|
155
|
+
var rowUpdates = sheetRowUpdates.get(sheetIdStr);
|
|
156
|
+
if (!rowUpdates.has(rowIdx)) {
|
|
157
|
+
rowUpdates.set(rowIdx, new Map());
|
|
179
158
|
}
|
|
159
|
+
rowUpdates.get(rowIdx).set(colIdx, value);
|
|
180
160
|
}
|
|
181
|
-
else {
|
|
182
|
-
otherPatches.push(patch);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
187
|
-
finally {
|
|
188
|
-
try {
|
|
189
|
-
if (patches_13_1 && !patches_13_1.done && (_a = patches_13.return)) _a.call(patches_13);
|
|
190
161
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
var sheetRowUpdates = new Map();
|
|
196
|
-
try {
|
|
197
|
-
for (var cellUpdates_1 = tslib_1.__values(cellUpdates), cellUpdates_1_1 = cellUpdates_1.next(); !cellUpdates_1_1.done; cellUpdates_1_1 = cellUpdates_1.next()) {
|
|
198
|
-
var _j = tslib_1.__read(cellUpdates_1_1.value, 2), _k = _j[1], sheetIdStr = _k.sheetIdStr, rowIdx = _k.rowIdx, colIdx = _k.colIdx, value = _k.value;
|
|
199
|
-
if (!sheetRowUpdates.has(sheetIdStr)) {
|
|
200
|
-
sheetRowUpdates.set(sheetIdStr, new Map());
|
|
201
|
-
}
|
|
202
|
-
var rowUpdates = sheetRowUpdates.get(sheetIdStr);
|
|
203
|
-
if (!rowUpdates.has(rowIdx)) {
|
|
204
|
-
rowUpdates.set(rowIdx, new Map());
|
|
162
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
163
|
+
finally {
|
|
164
|
+
try {
|
|
165
|
+
if (pendingCellUpdates_1_1 && !pendingCellUpdates_1_1.done && (_a = pendingCellUpdates_1.return)) _a.call(pendingCellUpdates_1);
|
|
205
166
|
}
|
|
206
|
-
|
|
167
|
+
finally { if (e_3) throw e_3.error; }
|
|
207
168
|
}
|
|
208
|
-
}
|
|
209
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
210
|
-
finally {
|
|
211
169
|
try {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
var _l = tslib_1.__read(sheetRowUpdates_1_1.value, 2), sheetIdStr = _l[0], rowUpdates = _l[1];
|
|
220
|
-
var ysheet = (0, exports.getSheetFromYSheetData)(ySheetData, sheetIdStr);
|
|
221
|
-
try {
|
|
222
|
-
for (var rowUpdates_1 = (e_5 = void 0, tslib_1.__values(rowUpdates)), rowUpdates_1_1 = rowUpdates_1.next(); !rowUpdates_1_1.done; rowUpdates_1_1 = rowUpdates_1.next()) {
|
|
223
|
-
var _m = tslib_1.__read(rowUpdates_1_1.value, 2), rowIdx = _m[0], colUpdates = _m[1];
|
|
224
|
-
var rowData = (0, exports.getRowDataFromSheet)(ysheet, rowIdx);
|
|
225
|
-
try {
|
|
226
|
-
for (var colUpdates_1 = (e_6 = void 0, tslib_1.__values(colUpdates)), colUpdates_1_1 = colUpdates_1.next(); !colUpdates_1_1.done; colUpdates_1_1 = colUpdates_1.next()) {
|
|
227
|
-
var _o = tslib_1.__read(colUpdates_1_1.value, 2), colIdx = _o[0], value = _o[1];
|
|
228
|
-
(0, exports.setCellDataInRowData)(rowData, colIdx, value);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
232
|
-
finally {
|
|
170
|
+
for (var sheetRowUpdates_1 = tslib_1.__values(sheetRowUpdates), sheetRowUpdates_1_1 = sheetRowUpdates_1.next(); !sheetRowUpdates_1_1.done; sheetRowUpdates_1_1 = sheetRowUpdates_1.next()) {
|
|
171
|
+
var _g = tslib_1.__read(sheetRowUpdates_1_1.value, 2), sheetIdStr = _g[0], rowUpdates = _g[1];
|
|
172
|
+
var ysheet = (0, exports.getSheetFromYSheetData)(ySheetData, sheetIdStr);
|
|
173
|
+
try {
|
|
174
|
+
for (var rowUpdates_1 = (e_5 = void 0, tslib_1.__values(rowUpdates)), rowUpdates_1_1 = rowUpdates_1.next(); !rowUpdates_1_1.done; rowUpdates_1_1 = rowUpdates_1.next()) {
|
|
175
|
+
var _h = tslib_1.__read(rowUpdates_1_1.value, 2), rowIdx = _h[0], colUpdates = _h[1];
|
|
176
|
+
var rowData = (0, exports.getRowDataFromSheet)(ysheet, rowIdx);
|
|
233
177
|
try {
|
|
234
|
-
|
|
178
|
+
for (var colUpdates_1 = (e_6 = void 0, tslib_1.__values(colUpdates)), colUpdates_1_1 = colUpdates_1.next(); !colUpdates_1_1.done; colUpdates_1_1 = colUpdates_1.next()) {
|
|
179
|
+
var _j = tslib_1.__read(colUpdates_1_1.value, 2), colIdx = _j[0], value = _j[1];
|
|
180
|
+
(0, exports.setCellDataInRowData)(rowData, colIdx, value);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
184
|
+
finally {
|
|
185
|
+
try {
|
|
186
|
+
if (colUpdates_1_1 && !colUpdates_1_1.done && (_d = colUpdates_1.return)) _d.call(colUpdates_1);
|
|
187
|
+
}
|
|
188
|
+
finally { if (e_6) throw e_6.error; }
|
|
235
189
|
}
|
|
236
|
-
finally { if (e_6) throw e_6.error; }
|
|
237
190
|
}
|
|
238
191
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
192
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
193
|
+
finally {
|
|
194
|
+
try {
|
|
195
|
+
if (rowUpdates_1_1 && !rowUpdates_1_1.done && (_c = rowUpdates_1.return)) _c.call(rowUpdates_1);
|
|
196
|
+
}
|
|
197
|
+
finally { if (e_5) throw e_5.error; }
|
|
244
198
|
}
|
|
245
|
-
finally { if (e_5) throw e_5.error; }
|
|
246
199
|
}
|
|
247
200
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
201
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
202
|
+
finally {
|
|
203
|
+
try {
|
|
204
|
+
if (sheetRowUpdates_1_1 && !sheetRowUpdates_1_1.done && (_b = sheetRowUpdates_1.return)) _b.call(sheetRowUpdates_1);
|
|
205
|
+
}
|
|
206
|
+
finally { if (e_4) throw e_4.error; }
|
|
253
207
|
}
|
|
254
|
-
|
|
255
|
-
}
|
|
208
|
+
pendingCellUpdates.clear();
|
|
209
|
+
};
|
|
256
210
|
// Process non-cell-level patches using original logic
|
|
257
211
|
var processPatch = function (_a) {
|
|
258
212
|
var op = _a.op, path = _a.path, value = _a.value;
|
|
@@ -369,8 +323,40 @@ var addSheetDataPatches = function (ySheetData, patches) {
|
|
|
369
323
|
}
|
|
370
324
|
}
|
|
371
325
|
};
|
|
372
|
-
|
|
373
|
-
|
|
326
|
+
try {
|
|
327
|
+
for (var patches_13 = tslib_1.__values(patches), patches_13_1 = patches_13.next(); !patches_13_1.done; patches_13_1 = patches_13.next()) {
|
|
328
|
+
var patch = patches_13_1.value;
|
|
329
|
+
var op = patch.op, path = patch.path, value = patch.value;
|
|
330
|
+
var _b = tslib_1.__read(path, 1), sheetIdRaw = _b[0];
|
|
331
|
+
if (typeof sheetIdRaw !== "undefined" &&
|
|
332
|
+
path.length === 4 &&
|
|
333
|
+
(op === "replace" || op === "add" || op === "remove")) {
|
|
334
|
+
// [sheetId, rowIndex, 'values', columnIndex] - single cell update (most common in paste)
|
|
335
|
+
var _c = tslib_1.__read(path, 4), rowIndex = _c[1], columnIndex = _c[3];
|
|
336
|
+
// Use string representation for sheet ID to handle both string and numeric IDs
|
|
337
|
+
var sheetIdStr = String(sheetIdRaw);
|
|
338
|
+
var rowIdx = Number(rowIndex);
|
|
339
|
+
var colIdx = Number(columnIndex);
|
|
340
|
+
pendingCellUpdates.set("".concat(sheetIdStr, ":").concat(rowIdx, ":").concat(colIdx), {
|
|
341
|
+
sheetIdStr: sheetIdStr,
|
|
342
|
+
rowIdx: rowIdx,
|
|
343
|
+
colIdx: colIdx,
|
|
344
|
+
value: op === "remove" ? null : value,
|
|
345
|
+
});
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
flushPendingCellUpdates();
|
|
349
|
+
processPatch(patch);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
353
|
+
finally {
|
|
354
|
+
try {
|
|
355
|
+
if (patches_13_1 && !patches_13_1.done && (_a = patches_13.return)) _a.call(patches_13);
|
|
356
|
+
}
|
|
357
|
+
finally { if (e_2) throw e_2.error; }
|
|
358
|
+
}
|
|
359
|
+
flushPendingCellUpdates();
|
|
374
360
|
};
|
|
375
361
|
exports.addSheetDataPatches = addSheetDataPatches;
|
|
376
362
|
var getSheetFromYSheetData = function (ySheetData, sheetId) {
|
|
@@ -657,7 +643,12 @@ var updateArrayType = function (yarray, patches) {
|
|
|
657
643
|
updatedItem = (0, cloneDeep_1.default)(baseItem);
|
|
658
644
|
pending = { index: index, item: updatedItem };
|
|
659
645
|
}
|
|
660
|
-
|
|
646
|
+
// Clone the value too: immer auto-freezes the state its patches point
|
|
647
|
+
// into, so a later patch of the same batch that writes INSIDE an object
|
|
648
|
+
// this one placed (`rowMetadata/4` = `{ outlineLevel: 1 }`, then
|
|
649
|
+
// `rowMetadata/4/outlineLevel` = 2 — a row grouped twice by one
|
|
650
|
+
// Subtotal) would otherwise hit a frozen object and be dropped.
|
|
651
|
+
(0, set_1.default)(updatedItem, nestedPath, (0, cloneDeep_1.default)(value));
|
|
661
652
|
}
|
|
662
653
|
}
|
|
663
654
|
else if (op === "remove") {
|
|
@@ -1193,82 +1184,7 @@ exports.getSheetDataV3 = getSheetDataV3;
|
|
|
1193
1184
|
* 2. Processing all cell updates in a single pass
|
|
1194
1185
|
*/
|
|
1195
1186
|
var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
1196
|
-
var e_13, _a
|
|
1197
|
-
// Optimization: Pre-process and consolidate cell-level patches
|
|
1198
|
-
// For bulk operations like paste (10k+ rows), this dramatically reduces overhead
|
|
1199
|
-
var cellUpdates = new Map();
|
|
1200
|
-
var otherPatches = [];
|
|
1201
|
-
try {
|
|
1202
|
-
// First pass: categorize and consolidate patches
|
|
1203
|
-
for (var patches_15 = tslib_1.__values(patches), patches_15_1 = patches_15.next(); !patches_15_1.done; patches_15_1 = patches_15.next()) {
|
|
1204
|
-
var patch = patches_15_1.value;
|
|
1205
|
-
var op = patch.op, path = patch.path, value = patch.value;
|
|
1206
|
-
var _c = tslib_1.__read(path, 1), sheetIdRaw = _c[0];
|
|
1207
|
-
// Handle undefined sheetId separately (full replace)
|
|
1208
|
-
if (typeof sheetIdRaw === "undefined") {
|
|
1209
|
-
otherPatches.push(patch);
|
|
1210
|
-
continue;
|
|
1211
|
-
}
|
|
1212
|
-
var sheetId = Number(sheetIdRaw);
|
|
1213
|
-
if (op === "replace" || op === "add") {
|
|
1214
|
-
// [sheetId, rowIndex, 'values', columnIndex] - Single cell update (most common in paste)
|
|
1215
|
-
if (path.length === 4) {
|
|
1216
|
-
var _d = tslib_1.__read(path, 4), rowIndex = _d[1], columnIndex = _d[3];
|
|
1217
|
-
var rowIdx = Number(rowIndex);
|
|
1218
|
-
var colIdx = Number(columnIndex);
|
|
1219
|
-
var key = (0, exports.createCellKeyV3)(sheetId, rowIdx, colIdx);
|
|
1220
|
-
// Later patches override earlier ones for the same cell
|
|
1221
|
-
cellUpdates.set(key, { sheetId: sheetId, rowIdx: rowIdx, colIdx: colIdx, value: value });
|
|
1222
|
-
}
|
|
1223
|
-
else {
|
|
1224
|
-
// Row-level or sheet-level updates
|
|
1225
|
-
otherPatches.push(patch);
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
else if (op === "remove") {
|
|
1229
|
-
if (path.length === 4) {
|
|
1230
|
-
var _e = tslib_1.__read(path, 4), rowIndex = _e[1], columnIndex = _e[3];
|
|
1231
|
-
var rowIdx = Number(rowIndex);
|
|
1232
|
-
var colIdx = Number(columnIndex);
|
|
1233
|
-
var key = (0, exports.createCellKeyV3)(sheetId, rowIdx, colIdx);
|
|
1234
|
-
cellUpdates.set(key, { sheetId: sheetId, rowIdx: rowIdx, colIdx: colIdx, value: null });
|
|
1235
|
-
}
|
|
1236
|
-
else {
|
|
1237
|
-
otherPatches.push(patch);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
else {
|
|
1241
|
-
otherPatches.push(patch);
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
1246
|
-
finally {
|
|
1247
|
-
try {
|
|
1248
|
-
if (patches_15_1 && !patches_15_1.done && (_a = patches_15.return)) _a.call(patches_15);
|
|
1249
|
-
}
|
|
1250
|
-
finally { if (e_13) throw e_13.error; }
|
|
1251
|
-
}
|
|
1252
|
-
try {
|
|
1253
|
-
// Second pass: Apply consolidated cell updates in batch
|
|
1254
|
-
// This is much faster than processing each patch individually
|
|
1255
|
-
for (var cellUpdates_2 = tslib_1.__values(cellUpdates), cellUpdates_2_1 = cellUpdates_2.next(); !cellUpdates_2_1.done; cellUpdates_2_1 = cellUpdates_2.next()) {
|
|
1256
|
-
var _f = tslib_1.__read(cellUpdates_2_1.value, 2), key = _f[0], _g = _f[1], sheetId = _g.sheetId, rowIdx = _g.rowIdx, colIdx = _g.colIdx, value = _g.value;
|
|
1257
|
-
if (value) {
|
|
1258
|
-
ySheetDataV3.set(key, (0, exports.createCellDataV3)(value, sheetId, rowIdx, colIdx));
|
|
1259
|
-
}
|
|
1260
|
-
else {
|
|
1261
|
-
ySheetDataV3.delete(key);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
|
1266
|
-
finally {
|
|
1267
|
-
try {
|
|
1268
|
-
if (cellUpdates_2_1 && !cellUpdates_2_1.done && (_b = cellUpdates_2.return)) _b.call(cellUpdates_2);
|
|
1269
|
-
}
|
|
1270
|
-
finally { if (e_14) throw e_14.error; }
|
|
1271
|
-
}
|
|
1187
|
+
var e_13, _a;
|
|
1272
1188
|
// Row-targeted patches (e.g. the per-shifted-row patches an immer array
|
|
1273
1189
|
// splice emits for a row insert/delete) previously scanned the entire flat
|
|
1274
1190
|
// cell map once per patch — O(patches × totalCells), which freezes the tab
|
|
@@ -1280,7 +1196,7 @@ var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
|
1280
1196
|
return "".concat(sheetId, ":").concat(rowIdx);
|
|
1281
1197
|
};
|
|
1282
1198
|
var ensureRowCellKeyIndex = function () {
|
|
1283
|
-
var
|
|
1199
|
+
var e_14, _a;
|
|
1284
1200
|
if (rowCellKeyIndex) {
|
|
1285
1201
|
return rowCellKeyIndex;
|
|
1286
1202
|
}
|
|
@@ -1297,12 +1213,12 @@ var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
|
1297
1213
|
keys.add(key);
|
|
1298
1214
|
}
|
|
1299
1215
|
}
|
|
1300
|
-
catch (
|
|
1216
|
+
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
|
1301
1217
|
finally {
|
|
1302
1218
|
try {
|
|
1303
1219
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1304
1220
|
}
|
|
1305
|
-
finally { if (
|
|
1221
|
+
finally { if (e_14) throw e_14.error; }
|
|
1306
1222
|
}
|
|
1307
1223
|
return rowCellKeyIndex;
|
|
1308
1224
|
};
|
|
@@ -1318,8 +1234,12 @@ var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
|
1318
1234
|
}
|
|
1319
1235
|
keys.add(key);
|
|
1320
1236
|
};
|
|
1237
|
+
var untrackCellKey = function (sheetId, rowIdx, key) {
|
|
1238
|
+
var _a;
|
|
1239
|
+
(_a = rowCellKeyIndex === null || rowCellKeyIndex === void 0 ? void 0 : rowCellKeyIndex.get(rowIndexKey(sheetId, rowIdx))) === null || _a === void 0 ? void 0 : _a.delete(key);
|
|
1240
|
+
};
|
|
1321
1241
|
var deleteRowCells = function (sheetId, rowIdx) {
|
|
1322
|
-
var
|
|
1242
|
+
var e_15, _a;
|
|
1323
1243
|
var keys = ensureRowCellKeyIndex().get(rowIndexKey(sheetId, rowIdx));
|
|
1324
1244
|
if (!keys) {
|
|
1325
1245
|
return;
|
|
@@ -1330,17 +1250,17 @@ var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
|
1330
1250
|
ySheetDataV3.delete(key);
|
|
1331
1251
|
}
|
|
1332
1252
|
}
|
|
1333
|
-
catch (
|
|
1253
|
+
catch (e_15_1) { e_15 = { error: e_15_1 }; }
|
|
1334
1254
|
finally {
|
|
1335
1255
|
try {
|
|
1336
1256
|
if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
|
|
1337
1257
|
}
|
|
1338
|
-
finally { if (
|
|
1258
|
+
finally { if (e_15) throw e_15.error; }
|
|
1339
1259
|
}
|
|
1340
1260
|
rowCellKeyIndex.delete(rowIndexKey(sheetId, rowIdx));
|
|
1341
1261
|
};
|
|
1342
1262
|
var dropSheetFromIndex = function (sheetId) {
|
|
1343
|
-
var
|
|
1263
|
+
var e_16, _a;
|
|
1344
1264
|
if (!rowCellKeyIndex) {
|
|
1345
1265
|
return;
|
|
1346
1266
|
}
|
|
@@ -1353,13 +1273,46 @@ var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
|
1353
1273
|
}
|
|
1354
1274
|
}
|
|
1355
1275
|
}
|
|
1356
|
-
catch (
|
|
1276
|
+
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
|
1357
1277
|
finally {
|
|
1358
1278
|
try {
|
|
1359
1279
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1360
1280
|
}
|
|
1281
|
+
finally { if (e_16) throw e_16.error; }
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
// Optimization: consecutive cell-level patches are consolidated (later
|
|
1285
|
+
// patches override earlier ones for the same cell) and applied together —
|
|
1286
|
+
// for bulk operations like paste (10k+ rows) this dramatically reduces
|
|
1287
|
+
// overhead. They are never reordered ACROSS a row-, sheet- or document-level
|
|
1288
|
+
// patch, though: a history entry that composes a row insert with writes into
|
|
1289
|
+
// the inserted row (Data → Subtotal) carries the insert's per-row replaces
|
|
1290
|
+
// and the writes' cell patches in that order, and a row replace applied
|
|
1291
|
+
// after the writes it precedes would delete them.
|
|
1292
|
+
var pendingCellUpdates = new Map();
|
|
1293
|
+
var flushPendingCellUpdates = function () {
|
|
1294
|
+
var e_17, _a;
|
|
1295
|
+
try {
|
|
1296
|
+
for (var pendingCellUpdates_2 = tslib_1.__values(pendingCellUpdates), pendingCellUpdates_2_1 = pendingCellUpdates_2.next(); !pendingCellUpdates_2_1.done; pendingCellUpdates_2_1 = pendingCellUpdates_2.next()) {
|
|
1297
|
+
var _b = tslib_1.__read(pendingCellUpdates_2_1.value, 2), key = _b[0], _c = _b[1], sheetId = _c.sheetId, rowIdx = _c.rowIdx, colIdx = _c.colIdx, value = _c.value;
|
|
1298
|
+
if (value) {
|
|
1299
|
+
ySheetDataV3.set(key, (0, exports.createCellDataV3)(value, sheetId, rowIdx, colIdx));
|
|
1300
|
+
trackCellKeySet(sheetId, rowIdx, key);
|
|
1301
|
+
}
|
|
1302
|
+
else {
|
|
1303
|
+
ySheetDataV3.delete(key);
|
|
1304
|
+
untrackCellKey(sheetId, rowIdx, key);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
catch (e_17_1) { e_17 = { error: e_17_1 }; }
|
|
1309
|
+
finally {
|
|
1310
|
+
try {
|
|
1311
|
+
if (pendingCellUpdates_2_1 && !pendingCellUpdates_2_1.done && (_a = pendingCellUpdates_2.return)) _a.call(pendingCellUpdates_2);
|
|
1312
|
+
}
|
|
1361
1313
|
finally { if (e_17) throw e_17.error; }
|
|
1362
1314
|
}
|
|
1315
|
+
pendingCellUpdates.clear();
|
|
1363
1316
|
};
|
|
1364
1317
|
// Process non-cell-level patches using original logic
|
|
1365
1318
|
var processPatch = function (_a) {
|
|
@@ -1551,8 +1504,39 @@ var addSheetDataPatchesV3 = function (ySheetDataV3, patches) {
|
|
|
1551
1504
|
}
|
|
1552
1505
|
}
|
|
1553
1506
|
};
|
|
1554
|
-
|
|
1555
|
-
|
|
1507
|
+
try {
|
|
1508
|
+
for (var patches_15 = tslib_1.__values(patches), patches_15_1 = patches_15.next(); !patches_15_1.done; patches_15_1 = patches_15.next()) {
|
|
1509
|
+
var patch = patches_15_1.value;
|
|
1510
|
+
var op = patch.op, path = patch.path, value = patch.value;
|
|
1511
|
+
var _b = tslib_1.__read(path, 1), sheetIdRaw = _b[0];
|
|
1512
|
+
if (typeof sheetIdRaw !== "undefined" &&
|
|
1513
|
+
path.length === 4 &&
|
|
1514
|
+
(op === "replace" || op === "add" || op === "remove")) {
|
|
1515
|
+
// [sheetId, rowIndex, 'values', columnIndex] - single cell update (most common in paste)
|
|
1516
|
+
var _c = tslib_1.__read(path, 4), rowIndex = _c[1], columnIndex = _c[3];
|
|
1517
|
+
var sheetId = Number(sheetIdRaw);
|
|
1518
|
+
var rowIdx = Number(rowIndex);
|
|
1519
|
+
var colIdx = Number(columnIndex);
|
|
1520
|
+
pendingCellUpdates.set((0, exports.createCellKeyV3)(sheetId, rowIdx, colIdx), {
|
|
1521
|
+
sheetId: sheetId,
|
|
1522
|
+
rowIdx: rowIdx,
|
|
1523
|
+
colIdx: colIdx,
|
|
1524
|
+
value: op === "remove" ? null : value,
|
|
1525
|
+
});
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
flushPendingCellUpdates();
|
|
1529
|
+
processPatch(patch);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
1533
|
+
finally {
|
|
1534
|
+
try {
|
|
1535
|
+
if (patches_15_1 && !patches_15_1.done && (_a = patches_15.return)) _a.call(patches_15);
|
|
1536
|
+
}
|
|
1537
|
+
finally { if (e_13) throw e_13.error; }
|
|
1538
|
+
}
|
|
1539
|
+
flushPendingCellUpdates();
|
|
1556
1540
|
};
|
|
1557
1541
|
exports.addSheetDataPatchesV3 = addSheetDataPatchesV3;
|
|
1558
1542
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../../helpers.ts","../../index.ts","../../observables.ts","../../types.ts","../../use-yspreadsheet-v2.ts","../../use-yspreadsheet.ts","../../vitest.config.ts"
|
|
1
|
+
{"root":["../../helpers.ts","../../index.ts","../../observables.ts","../../types.ts","../../use-yspreadsheet-v2.ts","../../use-yspreadsheet.ts","../../vitest.config.ts"],"version":"5.8.3"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,KAAK,EAEX,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,iCAAiC,CAAC;AAWzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAOzB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAEV,SAAS,EACT,UAAU,EACV,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;QACjC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EAAE,CAAC;IACJ,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,CAAC,CAAC,GAAG,EACV,QAAQ,MAAM,GAAG,MAAM,EACvB,SAAS,CACP,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAC9B,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CACtC,EAAE,EACH,SAAS,OAAO,GAAG,MAAM,GAAG,SAAS,EACrC,mBAAmB,IAAI,GAAG,IAAI,SAyG/B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAC7B,SAAS,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/helpers.js
CHANGED
|
@@ -115,76 +115,39 @@ export const applyPatchesToYDoc = (doc, userId, patches, source, sheetDataVersio
|
|
|
115
115
|
* 2. Grouping updates by sheet/row for efficient batch application
|
|
116
116
|
*/
|
|
117
117
|
export const addSheetDataPatches = (ySheetData, patches) => {
|
|
118
|
-
// Optimization:
|
|
119
|
-
//
|
|
118
|
+
// Optimization: consecutive cell-level patches are consolidated (later
|
|
119
|
+
// patches override earlier ones for the same cell) and applied together,
|
|
120
|
+
// grouped by sheet and row so bulk operations like paste (10k+ rows) cost
|
|
121
|
+
// one row lookup per row. They are never reordered ACROSS a row- or
|
|
122
|
+
// sheet-level patch (see `addSheetDataPatchesV3`).
|
|
120
123
|
// Key format: "sheetId:rowIndex:columnIndex"
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const { op, path, value } = patch;
|
|
126
|
-
const [sheetIdRaw] = path;
|
|
127
|
-
// Handle undefined sheetId separately (full replace)
|
|
128
|
-
if (typeof sheetIdRaw === "undefined") {
|
|
129
|
-
otherPatches.push(patch);
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
// Use string representation for sheet ID to handle both string and numeric IDs
|
|
133
|
-
const sheetIdStr = String(sheetIdRaw);
|
|
134
|
-
if (op === "replace" || op === "add") {
|
|
135
|
-
// [sheetId, rowIndex, 'values', columnIndex] - Single cell update (most common in paste)
|
|
136
|
-
if (path.length === 4) {
|
|
137
|
-
const [, rowIndex, , columnIndex] = path;
|
|
138
|
-
const rowIdx = Number(rowIndex);
|
|
139
|
-
const colIdx = Number(columnIndex);
|
|
140
|
-
const key = `${sheetIdStr}:${rowIdx}:${colIdx}`;
|
|
141
|
-
// Later patches override earlier ones for the same cell
|
|
142
|
-
cellUpdates.set(key, { sheetIdStr, rowIdx, colIdx, value });
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
// Row-level or sheet-level updates
|
|
146
|
-
otherPatches.push(patch);
|
|
147
|
-
}
|
|
124
|
+
const pendingCellUpdates = new Map();
|
|
125
|
+
const flushPendingCellUpdates = () => {
|
|
126
|
+
if (pendingCellUpdates.size === 0) {
|
|
127
|
+
return;
|
|
148
128
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const colIdx = Number(columnIndex);
|
|
154
|
-
const key = `${sheetIdStr}:${rowIdx}:${colIdx}`;
|
|
155
|
-
cellUpdates.set(key, { sheetIdStr, rowIdx, colIdx, value: null });
|
|
129
|
+
const sheetRowUpdates = new Map();
|
|
130
|
+
for (const [, { sheetIdStr, rowIdx, colIdx, value }] of pendingCellUpdates) {
|
|
131
|
+
if (!sheetRowUpdates.has(sheetIdStr)) {
|
|
132
|
+
sheetRowUpdates.set(sheetIdStr, new Map());
|
|
156
133
|
}
|
|
157
|
-
|
|
158
|
-
|
|
134
|
+
const rowUpdates = sheetRowUpdates.get(sheetIdStr);
|
|
135
|
+
if (!rowUpdates.has(rowIdx)) {
|
|
136
|
+
rowUpdates.set(rowIdx, new Map());
|
|
159
137
|
}
|
|
138
|
+
rowUpdates.get(rowIdx).set(colIdx, value);
|
|
160
139
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
for (const [, { sheetIdStr, rowIdx, colIdx, value }] of cellUpdates) {
|
|
169
|
-
if (!sheetRowUpdates.has(sheetIdStr)) {
|
|
170
|
-
sheetRowUpdates.set(sheetIdStr, new Map());
|
|
171
|
-
}
|
|
172
|
-
const rowUpdates = sheetRowUpdates.get(sheetIdStr);
|
|
173
|
-
if (!rowUpdates.has(rowIdx)) {
|
|
174
|
-
rowUpdates.set(rowIdx, new Map());
|
|
175
|
-
}
|
|
176
|
-
rowUpdates.get(rowIdx).set(colIdx, value);
|
|
177
|
-
}
|
|
178
|
-
// Apply batched cell updates
|
|
179
|
-
for (const [sheetIdStr, rowUpdates] of sheetRowUpdates) {
|
|
180
|
-
const ysheet = getSheetFromYSheetData(ySheetData, sheetIdStr);
|
|
181
|
-
for (const [rowIdx, colUpdates] of rowUpdates) {
|
|
182
|
-
const rowData = getRowDataFromSheet(ysheet, rowIdx);
|
|
183
|
-
for (const [colIdx, value] of colUpdates) {
|
|
184
|
-
setCellDataInRowData(rowData, colIdx, value);
|
|
140
|
+
for (const [sheetIdStr, rowUpdates] of sheetRowUpdates) {
|
|
141
|
+
const ysheet = getSheetFromYSheetData(ySheetData, sheetIdStr);
|
|
142
|
+
for (const [rowIdx, colUpdates] of rowUpdates) {
|
|
143
|
+
const rowData = getRowDataFromSheet(ysheet, rowIdx);
|
|
144
|
+
for (const [colIdx, value] of colUpdates) {
|
|
145
|
+
setCellDataInRowData(rowData, colIdx, value);
|
|
146
|
+
}
|
|
185
147
|
}
|
|
186
148
|
}
|
|
187
|
-
|
|
149
|
+
pendingCellUpdates.clear();
|
|
150
|
+
};
|
|
188
151
|
// Process non-cell-level patches using original logic
|
|
189
152
|
const processPatch = ({ op, path, value }) => {
|
|
190
153
|
let [sheetId] = path;
|
|
@@ -280,8 +243,30 @@ export const addSheetDataPatches = (ySheetData, patches) => {
|
|
|
280
243
|
}
|
|
281
244
|
}
|
|
282
245
|
};
|
|
283
|
-
|
|
284
|
-
|
|
246
|
+
for (const patch of patches) {
|
|
247
|
+
const { op, path, value } = patch;
|
|
248
|
+
const [sheetIdRaw] = path;
|
|
249
|
+
if (typeof sheetIdRaw !== "undefined" &&
|
|
250
|
+
path.length === 4 &&
|
|
251
|
+
(op === "replace" || op === "add" || op === "remove")) {
|
|
252
|
+
// [sheetId, rowIndex, 'values', columnIndex] - single cell update (most common in paste)
|
|
253
|
+
const [, rowIndex, , columnIndex] = path;
|
|
254
|
+
// Use string representation for sheet ID to handle both string and numeric IDs
|
|
255
|
+
const sheetIdStr = String(sheetIdRaw);
|
|
256
|
+
const rowIdx = Number(rowIndex);
|
|
257
|
+
const colIdx = Number(columnIndex);
|
|
258
|
+
pendingCellUpdates.set(`${sheetIdStr}:${rowIdx}:${colIdx}`, {
|
|
259
|
+
sheetIdStr,
|
|
260
|
+
rowIdx,
|
|
261
|
+
colIdx,
|
|
262
|
+
value: op === "remove" ? null : value,
|
|
263
|
+
});
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
flushPendingCellUpdates();
|
|
267
|
+
processPatch(patch);
|
|
268
|
+
}
|
|
269
|
+
flushPendingCellUpdates();
|
|
285
270
|
};
|
|
286
271
|
export const getSheetFromYSheetData = (ySheetData, sheetId) => {
|
|
287
272
|
const id = String(sheetId);
|
|
@@ -553,7 +538,12 @@ export const updateArrayType = (yarray, patches) => {
|
|
|
553
538
|
updatedItem = cloneDeep(baseItem);
|
|
554
539
|
pending = { index, item: updatedItem };
|
|
555
540
|
}
|
|
556
|
-
|
|
541
|
+
// Clone the value too: immer auto-freezes the state its patches point
|
|
542
|
+
// into, so a later patch of the same batch that writes INSIDE an object
|
|
543
|
+
// this one placed (`rowMetadata/4` = `{ outlineLevel: 1 }`, then
|
|
544
|
+
// `rowMetadata/4/outlineLevel` = 2 — a row grouped twice by one
|
|
545
|
+
// Subtotal) would otherwise hit a frozen object and be dropped.
|
|
546
|
+
set(updatedItem, nestedPath, cloneDeep(value));
|
|
557
547
|
}
|
|
558
548
|
}
|
|
559
549
|
else if (op === "remove") {
|
|
@@ -1002,61 +992,6 @@ export const getSheetDataV3 = (doc) => {
|
|
|
1002
992
|
* 2. Processing all cell updates in a single pass
|
|
1003
993
|
*/
|
|
1004
994
|
export const addSheetDataPatchesV3 = (ySheetDataV3, patches) => {
|
|
1005
|
-
// Optimization: Pre-process and consolidate cell-level patches
|
|
1006
|
-
// For bulk operations like paste (10k+ rows), this dramatically reduces overhead
|
|
1007
|
-
const cellUpdates = new Map();
|
|
1008
|
-
const otherPatches = [];
|
|
1009
|
-
// First pass: categorize and consolidate patches
|
|
1010
|
-
for (const patch of patches) {
|
|
1011
|
-
const { op, path, value } = patch;
|
|
1012
|
-
const [sheetIdRaw] = path;
|
|
1013
|
-
// Handle undefined sheetId separately (full replace)
|
|
1014
|
-
if (typeof sheetIdRaw === "undefined") {
|
|
1015
|
-
otherPatches.push(patch);
|
|
1016
|
-
continue;
|
|
1017
|
-
}
|
|
1018
|
-
const sheetId = Number(sheetIdRaw);
|
|
1019
|
-
if (op === "replace" || op === "add") {
|
|
1020
|
-
// [sheetId, rowIndex, 'values', columnIndex] - Single cell update (most common in paste)
|
|
1021
|
-
if (path.length === 4) {
|
|
1022
|
-
const [, rowIndex, , columnIndex] = path;
|
|
1023
|
-
const rowIdx = Number(rowIndex);
|
|
1024
|
-
const colIdx = Number(columnIndex);
|
|
1025
|
-
const key = createCellKeyV3(sheetId, rowIdx, colIdx);
|
|
1026
|
-
// Later patches override earlier ones for the same cell
|
|
1027
|
-
cellUpdates.set(key, { sheetId, rowIdx, colIdx, value });
|
|
1028
|
-
}
|
|
1029
|
-
else {
|
|
1030
|
-
// Row-level or sheet-level updates
|
|
1031
|
-
otherPatches.push(patch);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
else if (op === "remove") {
|
|
1035
|
-
if (path.length === 4) {
|
|
1036
|
-
const [, rowIndex, , columnIndex] = path;
|
|
1037
|
-
const rowIdx = Number(rowIndex);
|
|
1038
|
-
const colIdx = Number(columnIndex);
|
|
1039
|
-
const key = createCellKeyV3(sheetId, rowIdx, colIdx);
|
|
1040
|
-
cellUpdates.set(key, { sheetId, rowIdx, colIdx, value: null });
|
|
1041
|
-
}
|
|
1042
|
-
else {
|
|
1043
|
-
otherPatches.push(patch);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
else {
|
|
1047
|
-
otherPatches.push(patch);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
// Second pass: Apply consolidated cell updates in batch
|
|
1051
|
-
// This is much faster than processing each patch individually
|
|
1052
|
-
for (const [key, { sheetId, rowIdx, colIdx, value }] of cellUpdates) {
|
|
1053
|
-
if (value) {
|
|
1054
|
-
ySheetDataV3.set(key, createCellDataV3(value, sheetId, rowIdx, colIdx));
|
|
1055
|
-
}
|
|
1056
|
-
else {
|
|
1057
|
-
ySheetDataV3.delete(key);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
995
|
// Row-targeted patches (e.g. the per-shifted-row patches an immer array
|
|
1061
996
|
// splice emits for a row insert/delete) previously scanned the entire flat
|
|
1062
997
|
// cell map once per patch — O(patches × totalCells), which freezes the tab
|
|
@@ -1093,6 +1028,9 @@ export const addSheetDataPatchesV3 = (ySheetDataV3, patches) => {
|
|
|
1093
1028
|
}
|
|
1094
1029
|
keys.add(key);
|
|
1095
1030
|
};
|
|
1031
|
+
const untrackCellKey = (sheetId, rowIdx, key) => {
|
|
1032
|
+
rowCellKeyIndex?.get(rowIndexKey(sheetId, rowIdx))?.delete(key);
|
|
1033
|
+
};
|
|
1096
1034
|
const deleteRowCells = (sheetId, rowIdx) => {
|
|
1097
1035
|
const keys = ensureRowCellKeyIndex().get(rowIndexKey(sheetId, rowIdx));
|
|
1098
1036
|
if (!keys) {
|
|
@@ -1114,6 +1052,28 @@ export const addSheetDataPatchesV3 = (ySheetDataV3, patches) => {
|
|
|
1114
1052
|
}
|
|
1115
1053
|
}
|
|
1116
1054
|
};
|
|
1055
|
+
// Optimization: consecutive cell-level patches are consolidated (later
|
|
1056
|
+
// patches override earlier ones for the same cell) and applied together —
|
|
1057
|
+
// for bulk operations like paste (10k+ rows) this dramatically reduces
|
|
1058
|
+
// overhead. They are never reordered ACROSS a row-, sheet- or document-level
|
|
1059
|
+
// patch, though: a history entry that composes a row insert with writes into
|
|
1060
|
+
// the inserted row (Data → Subtotal) carries the insert's per-row replaces
|
|
1061
|
+
// and the writes' cell patches in that order, and a row replace applied
|
|
1062
|
+
// after the writes it precedes would delete them.
|
|
1063
|
+
const pendingCellUpdates = new Map();
|
|
1064
|
+
const flushPendingCellUpdates = () => {
|
|
1065
|
+
for (const [key, { sheetId, rowIdx, colIdx, value }] of pendingCellUpdates) {
|
|
1066
|
+
if (value) {
|
|
1067
|
+
ySheetDataV3.set(key, createCellDataV3(value, sheetId, rowIdx, colIdx));
|
|
1068
|
+
trackCellKeySet(sheetId, rowIdx, key);
|
|
1069
|
+
}
|
|
1070
|
+
else {
|
|
1071
|
+
ySheetDataV3.delete(key);
|
|
1072
|
+
untrackCellKey(sheetId, rowIdx, key);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
pendingCellUpdates.clear();
|
|
1076
|
+
};
|
|
1117
1077
|
// Process non-cell-level patches using original logic
|
|
1118
1078
|
const processPatch = ({ op, path, value }) => {
|
|
1119
1079
|
const [sheetIdRaw] = path;
|
|
@@ -1264,8 +1224,29 @@ export const addSheetDataPatchesV3 = (ySheetDataV3, patches) => {
|
|
|
1264
1224
|
}
|
|
1265
1225
|
}
|
|
1266
1226
|
};
|
|
1267
|
-
|
|
1268
|
-
|
|
1227
|
+
for (const patch of patches) {
|
|
1228
|
+
const { op, path, value } = patch;
|
|
1229
|
+
const [sheetIdRaw] = path;
|
|
1230
|
+
if (typeof sheetIdRaw !== "undefined" &&
|
|
1231
|
+
path.length === 4 &&
|
|
1232
|
+
(op === "replace" || op === "add" || op === "remove")) {
|
|
1233
|
+
// [sheetId, rowIndex, 'values', columnIndex] - single cell update (most common in paste)
|
|
1234
|
+
const [, rowIndex, , columnIndex] = path;
|
|
1235
|
+
const sheetId = Number(sheetIdRaw);
|
|
1236
|
+
const rowIdx = Number(rowIndex);
|
|
1237
|
+
const colIdx = Number(columnIndex);
|
|
1238
|
+
pendingCellUpdates.set(createCellKeyV3(sheetId, rowIdx, colIdx), {
|
|
1239
|
+
sheetId,
|
|
1240
|
+
rowIdx,
|
|
1241
|
+
colIdx,
|
|
1242
|
+
value: op === "remove" ? null : value,
|
|
1243
|
+
});
|
|
1244
|
+
continue;
|
|
1245
|
+
}
|
|
1246
|
+
flushPendingCellUpdates();
|
|
1247
|
+
processPatch(patch);
|
|
1248
|
+
}
|
|
1249
|
+
flushPendingCellUpdates();
|
|
1269
1250
|
};
|
|
1270
1251
|
/**
|
|
1271
1252
|
* Process V3 events and return updated sheet data
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../../helpers.ts","../../index.ts","../../observables.ts","../../types.ts","../../use-yspreadsheet-v2.ts","../../use-yspreadsheet.ts","../../vitest.config.ts"
|
|
1
|
+
{"root":["../../helpers.ts","../../index.ts","../../observables.ts","../../types.ts","../../use-yspreadsheet-v2.ts","../../use-yspreadsheet.ts","../../vitest.config.ts"],"version":"5.8.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rowsncolumns/y-spreadsheet",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.2",
|
|
4
4
|
"main": "./dist/cjs/index.js",
|
|
5
5
|
"module": "./dist/esm/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"build:watch": "tsc -p ./tsconfig.esm.json --watch",
|
|
18
18
|
"lint": "eslint . --ext .ts,.tsx",
|
|
19
19
|
"test": "vitest --run",
|
|
20
|
-
"types": "tsc -p . --noEmit"
|
|
20
|
+
"types": "tsc -p . --noEmit",
|
|
21
|
+
"types:specs": "node ../../scripts/typecheck-specs.mjs",
|
|
22
|
+
"types:specs:update": "node ../../scripts/typecheck-specs.mjs --update"
|
|
21
23
|
},
|
|
22
24
|
"files": [
|
|
23
25
|
"dist"
|
|
@@ -32,16 +34,17 @@
|
|
|
32
34
|
"sideEffects": false,
|
|
33
35
|
"devDependencies": {
|
|
34
36
|
"@hocuspocus/provider": "^3.1.1",
|
|
35
|
-
"@rowsncolumns/common-types": ">=5.
|
|
36
|
-
"@rowsncolumns/
|
|
37
|
-
"@rowsncolumns/
|
|
38
|
-
"@rowsncolumns/spreadsheet
|
|
39
|
-
"@rowsncolumns/
|
|
40
|
-
"@rowsncolumns/
|
|
37
|
+
"@rowsncolumns/common-types": ">=5.3.1",
|
|
38
|
+
"@rowsncolumns/fast-formula-parser": ">=6.2.41",
|
|
39
|
+
"@rowsncolumns/grid": ">=13.2.35",
|
|
40
|
+
"@rowsncolumns/spreadsheet": ">=10.4.1",
|
|
41
|
+
"@rowsncolumns/spreadsheet-state": ">=29.1.4",
|
|
42
|
+
"@rowsncolumns/ui": ">=16.0.3",
|
|
43
|
+
"@rowsncolumns/utils": ">=9.5.1",
|
|
44
|
+
"@types/lodash": "^4.17.17",
|
|
41
45
|
"react": "^19.1.0",
|
|
42
46
|
"react-dom": "^19.1.0",
|
|
43
47
|
"y-websocket": "^3.0.0",
|
|
44
|
-
"@types/lodash": "^4.17.17",
|
|
45
48
|
"yjs": "^13.6.27"
|
|
46
49
|
},
|
|
47
50
|
"peerDependencies": {
|
|
@@ -57,7 +60,7 @@
|
|
|
57
60
|
"yjs": ">=13.0.0"
|
|
58
61
|
},
|
|
59
62
|
"dependencies": {
|
|
60
|
-
"
|
|
61
|
-
"
|
|
63
|
+
"lodash": "^4.17.21",
|
|
64
|
+
"rxjs": "^7.8.2"
|
|
62
65
|
}
|
|
63
66
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batch-profile.spec.d.ts","sourceRoot":"","sources":["../../../profiling/batch-profile.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var tslib_1 = require("tslib");
|
|
4
|
-
/* @vitest-environment jsdom */
|
|
5
|
-
var react_1 = require("@testing-library/react");
|
|
6
|
-
var vitest_1 = require("vitest");
|
|
7
|
-
var Y = tslib_1.__importStar(require("yjs"));
|
|
8
|
-
var use_yspreadsheet_v2_1 = require("../use-yspreadsheet-v2");
|
|
9
|
-
vitest_1.vi.mock("@rowsncolumns/utils", function (importOriginal) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
10
|
-
var actual;
|
|
11
|
-
return tslib_1.__generator(this, function (_a) {
|
|
12
|
-
switch (_a.label) {
|
|
13
|
-
case 0: return [4 /*yield*/, importOriginal()];
|
|
14
|
-
case 1:
|
|
15
|
-
actual = _a.sent();
|
|
16
|
-
return [2 /*return*/, tslib_1.__assign(tslib_1.__assign({}, actual), { scheduleAfterPaint: function (callback) {
|
|
17
|
-
if (typeof requestAnimationFrame === "function") {
|
|
18
|
-
var frameId_1 = requestAnimationFrame(function () { return callback(); });
|
|
19
|
-
return function () {
|
|
20
|
-
if (typeof cancelAnimationFrame === "function") {
|
|
21
|
-
cancelAnimationFrame(frameId_1);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
var timeoutId = setTimeout(callback, 0);
|
|
26
|
-
return function () { return clearTimeout(timeoutId); };
|
|
27
|
-
} })];
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}); });
|
|
31
|
-
var parseEnvNumber = function (key, fallback) {
|
|
32
|
-
var value = Number(process.env[key]);
|
|
33
|
-
return Number.isFinite(value) ? value : fallback;
|
|
34
|
-
};
|
|
35
|
-
var testTimeoutMs = parseEnvNumber("PROFILE_TEST_TIMEOUT_MS", 30000);
|
|
36
|
-
var now = function () {
|
|
37
|
-
return typeof performance !== "undefined" && typeof performance.now === "function"
|
|
38
|
-
? performance.now()
|
|
39
|
-
: Date.now();
|
|
40
|
-
};
|
|
41
|
-
var createSheetDataPatchBatch = function (sheetId, startRow, rows, columns) {
|
|
42
|
-
var patches = [];
|
|
43
|
-
var _loop_1 = function (rowIndex) {
|
|
44
|
-
var absoluteRow = startRow + rowIndex;
|
|
45
|
-
var values = Array.from({ length: columns }, function (_, columnIndex) { return ({
|
|
46
|
-
value: "R".concat(absoluteRow, "C").concat(columnIndex),
|
|
47
|
-
}); });
|
|
48
|
-
patches.push([
|
|
49
|
-
{
|
|
50
|
-
sheetData: {
|
|
51
|
-
patches: [
|
|
52
|
-
{
|
|
53
|
-
op: "add",
|
|
54
|
-
path: [sheetId, absoluteRow],
|
|
55
|
-
value: { values: values },
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
inversePatches: [],
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
undefined,
|
|
62
|
-
]);
|
|
63
|
-
};
|
|
64
|
-
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
65
|
-
_loop_1(rowIndex);
|
|
66
|
-
}
|
|
67
|
-
return patches;
|
|
68
|
-
};
|
|
69
|
-
var waitForCondition = function (condition_1, timeoutMs_1) {
|
|
70
|
-
var args_1 = [];
|
|
71
|
-
for (var _i = 2; _i < arguments.length; _i++) {
|
|
72
|
-
args_1[_i - 2] = arguments[_i];
|
|
73
|
-
}
|
|
74
|
-
return tslib_1.__awaiter(void 0, tslib_1.__spreadArray([condition_1, timeoutMs_1], tslib_1.__read(args_1), false), void 0, function (condition, timeoutMs, intervalMs) {
|
|
75
|
-
var start;
|
|
76
|
-
if (intervalMs === void 0) { intervalMs = 25; }
|
|
77
|
-
return tslib_1.__generator(this, function (_a) {
|
|
78
|
-
switch (_a.label) {
|
|
79
|
-
case 0:
|
|
80
|
-
start = Date.now();
|
|
81
|
-
_a.label = 1;
|
|
82
|
-
case 1:
|
|
83
|
-
if (!(Date.now() - start < timeoutMs)) return [3 /*break*/, 3];
|
|
84
|
-
if (condition()) {
|
|
85
|
-
return [2 /*return*/];
|
|
86
|
-
}
|
|
87
|
-
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, intervalMs); })];
|
|
88
|
-
case 2:
|
|
89
|
-
_a.sent();
|
|
90
|
-
return [3 /*break*/, 1];
|
|
91
|
-
case 3: throw new Error("Profiling timed out while waiting for condition.");
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
};
|
|
96
|
-
(0, vitest_1.describe)("profiling: staggered broadcast patches", function () {
|
|
97
|
-
(0, vitest_1.it)("profiles large batch updates without data loss", function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
98
|
-
var sheetId, rowsPerCall, calls, columns, timeoutMs, totalRows, totalPatches, doc, transactSpy, result, memStart, enqueueStart, _loop_2, i, enqueueMs, applyStart, applyMs, sheetData, lastRow, lastValues, lastCell, memEnd, report;
|
|
99
|
-
var _a, _b;
|
|
100
|
-
return tslib_1.__generator(this, function (_c) {
|
|
101
|
-
switch (_c.label) {
|
|
102
|
-
case 0:
|
|
103
|
-
vitest_1.vi.useRealTimers();
|
|
104
|
-
sheetId = parseEnvNumber("PROFILE_SHEET_ID", 1);
|
|
105
|
-
rowsPerCall = parseEnvNumber("PROFILE_ROWS_PER_CALL", 150);
|
|
106
|
-
calls = parseEnvNumber("PROFILE_CALLS", 10);
|
|
107
|
-
columns = parseEnvNumber("PROFILE_COLUMNS", 20);
|
|
108
|
-
timeoutMs = parseEnvNumber("PROFILE_TIMEOUT_MS", 20000);
|
|
109
|
-
totalRows = rowsPerCall * calls;
|
|
110
|
-
totalPatches = totalRows;
|
|
111
|
-
doc = new Y.Doc();
|
|
112
|
-
transactSpy = vitest_1.vi.spyOn(doc, "transact");
|
|
113
|
-
result = (0, react_1.renderHook)(function () {
|
|
114
|
-
return (0, use_yspreadsheet_v2_1.useYSpreadsheetV2)({
|
|
115
|
-
userId: "user-1",
|
|
116
|
-
title: "Profiler",
|
|
117
|
-
sheetId: sheetId,
|
|
118
|
-
doc: doc,
|
|
119
|
-
calculateNow: vitest_1.vi.fn(),
|
|
120
|
-
initialSheets: [],
|
|
121
|
-
onChangeSheetData: vitest_1.vi.fn(),
|
|
122
|
-
onChangeSheets: vitest_1.vi.fn(),
|
|
123
|
-
onChangeTables: vitest_1.vi.fn(),
|
|
124
|
-
enqueueCalculation: vitest_1.vi.fn(),
|
|
125
|
-
enqueueGraphOperation: vitest_1.vi.fn(),
|
|
126
|
-
});
|
|
127
|
-
}).result;
|
|
128
|
-
memStart = (_a = process === null || process === void 0 ? void 0 : process.memoryUsage) === null || _a === void 0 ? void 0 : _a.call(process).heapUsed;
|
|
129
|
-
enqueueStart = now();
|
|
130
|
-
_loop_2 = function (i) {
|
|
131
|
-
var batch = createSheetDataPatchBatch(sheetId, i * rowsPerCall, rowsPerCall, columns);
|
|
132
|
-
(0, react_1.act)(function () {
|
|
133
|
-
result.current.onBroadcastPatch(batch);
|
|
134
|
-
});
|
|
135
|
-
};
|
|
136
|
-
for (i = 0; i < calls; i++) {
|
|
137
|
-
_loop_2(i);
|
|
138
|
-
}
|
|
139
|
-
enqueueMs = now() - enqueueStart;
|
|
140
|
-
applyStart = now();
|
|
141
|
-
return [4 /*yield*/, waitForCondition(function () {
|
|
142
|
-
var sheetData = doc.getMap("sheetDataV2").get(String(sheetId));
|
|
143
|
-
return (sheetData === null || sheetData === void 0 ? void 0 : sheetData.length) === totalRows;
|
|
144
|
-
}, timeoutMs)];
|
|
145
|
-
case 1:
|
|
146
|
-
_c.sent();
|
|
147
|
-
applyMs = now() - applyStart;
|
|
148
|
-
sheetData = doc.getMap("sheetDataV2").get(String(sheetId));
|
|
149
|
-
lastRow = sheetData === null || sheetData === void 0 ? void 0 : sheetData.get(totalRows - 1);
|
|
150
|
-
lastValues = lastRow === null || lastRow === void 0 ? void 0 : lastRow.get("values");
|
|
151
|
-
lastCell = lastValues === null || lastValues === void 0 ? void 0 : lastValues.get(columns - 1);
|
|
152
|
-
if (!lastCell || lastCell.value !== "R".concat(totalRows - 1, "C").concat(columns - 1)) {
|
|
153
|
-
throw new Error("Data loss detected: last cell value mismatch.");
|
|
154
|
-
}
|
|
155
|
-
memEnd = (_b = process === null || process === void 0 ? void 0 : process.memoryUsage) === null || _b === void 0 ? void 0 : _b.call(process).heapUsed;
|
|
156
|
-
report = {
|
|
157
|
-
sheetId: sheetId,
|
|
158
|
-
calls: calls,
|
|
159
|
-
rowsPerCall: rowsPerCall,
|
|
160
|
-
columns: columns,
|
|
161
|
-
totalRows: totalRows,
|
|
162
|
-
totalPatches: totalPatches,
|
|
163
|
-
enqueueMs: Math.round(enqueueMs),
|
|
164
|
-
applyMs: Math.round(applyMs),
|
|
165
|
-
transactBatches: transactSpy.mock.calls.length,
|
|
166
|
-
heapDeltaMB: typeof memStart === "number" && typeof memEnd === "number"
|
|
167
|
-
? Math.round(((memEnd - memStart) / 1024 / 1024) * 100) / 100
|
|
168
|
-
: "n/a",
|
|
169
|
-
};
|
|
170
|
-
console.table(report);
|
|
171
|
-
return [2 /*return*/];
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}); }, testTimeoutMs);
|
|
175
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batch-profile.spec.d.ts","sourceRoot":"","sources":["../../../profiling/batch-profile.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/* @vitest-environment jsdom */
|
|
2
|
-
import { act, renderHook } from "@testing-library/react";
|
|
3
|
-
import { describe, it, vi } from "vitest";
|
|
4
|
-
import * as Y from "yjs";
|
|
5
|
-
import { useYSpreadsheetV2 } from "../use-yspreadsheet-v2";
|
|
6
|
-
vi.mock("@rowsncolumns/utils", async (importOriginal) => {
|
|
7
|
-
const actual = await importOriginal();
|
|
8
|
-
return {
|
|
9
|
-
...actual,
|
|
10
|
-
scheduleAfterPaint: (callback) => {
|
|
11
|
-
if (typeof requestAnimationFrame === "function") {
|
|
12
|
-
const frameId = requestAnimationFrame(() => callback());
|
|
13
|
-
return () => {
|
|
14
|
-
if (typeof cancelAnimationFrame === "function") {
|
|
15
|
-
cancelAnimationFrame(frameId);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
const timeoutId = setTimeout(callback, 0);
|
|
20
|
-
return () => clearTimeout(timeoutId);
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
const parseEnvNumber = (key, fallback) => {
|
|
25
|
-
const value = Number(process.env[key]);
|
|
26
|
-
return Number.isFinite(value) ? value : fallback;
|
|
27
|
-
};
|
|
28
|
-
const testTimeoutMs = parseEnvNumber("PROFILE_TEST_TIMEOUT_MS", 30000);
|
|
29
|
-
const now = () => typeof performance !== "undefined" && typeof performance.now === "function"
|
|
30
|
-
? performance.now()
|
|
31
|
-
: Date.now();
|
|
32
|
-
const createSheetDataPatchBatch = (sheetId, startRow, rows, columns) => {
|
|
33
|
-
const patches = [];
|
|
34
|
-
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
35
|
-
const absoluteRow = startRow + rowIndex;
|
|
36
|
-
const values = Array.from({ length: columns }, (_, columnIndex) => ({
|
|
37
|
-
value: `R${absoluteRow}C${columnIndex}`,
|
|
38
|
-
}));
|
|
39
|
-
patches.push([
|
|
40
|
-
{
|
|
41
|
-
sheetData: {
|
|
42
|
-
patches: [
|
|
43
|
-
{
|
|
44
|
-
op: "add",
|
|
45
|
-
path: [sheetId, absoluteRow],
|
|
46
|
-
value: { values },
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
inversePatches: [],
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
undefined,
|
|
53
|
-
]);
|
|
54
|
-
}
|
|
55
|
-
return patches;
|
|
56
|
-
};
|
|
57
|
-
const waitForCondition = async (condition, timeoutMs, intervalMs = 25) => {
|
|
58
|
-
const start = Date.now();
|
|
59
|
-
while (Date.now() - start < timeoutMs) {
|
|
60
|
-
if (condition()) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
64
|
-
}
|
|
65
|
-
throw new Error("Profiling timed out while waiting for condition.");
|
|
66
|
-
};
|
|
67
|
-
describe("profiling: staggered broadcast patches", () => {
|
|
68
|
-
it("profiles large batch updates without data loss", async () => {
|
|
69
|
-
vi.useRealTimers();
|
|
70
|
-
const sheetId = parseEnvNumber("PROFILE_SHEET_ID", 1);
|
|
71
|
-
const rowsPerCall = parseEnvNumber("PROFILE_ROWS_PER_CALL", 150);
|
|
72
|
-
const calls = parseEnvNumber("PROFILE_CALLS", 10);
|
|
73
|
-
const columns = parseEnvNumber("PROFILE_COLUMNS", 20);
|
|
74
|
-
const timeoutMs = parseEnvNumber("PROFILE_TIMEOUT_MS", 20000);
|
|
75
|
-
const totalRows = rowsPerCall * calls;
|
|
76
|
-
const totalPatches = totalRows;
|
|
77
|
-
const doc = new Y.Doc();
|
|
78
|
-
const transactSpy = vi.spyOn(doc, "transact");
|
|
79
|
-
const { result } = renderHook(() => useYSpreadsheetV2({
|
|
80
|
-
userId: "user-1",
|
|
81
|
-
title: "Profiler",
|
|
82
|
-
sheetId,
|
|
83
|
-
doc,
|
|
84
|
-
calculateNow: vi.fn(),
|
|
85
|
-
initialSheets: [],
|
|
86
|
-
onChangeSheetData: vi.fn(),
|
|
87
|
-
onChangeSheets: vi.fn(),
|
|
88
|
-
onChangeTables: vi.fn(),
|
|
89
|
-
enqueueCalculation: vi.fn(),
|
|
90
|
-
enqueueGraphOperation: vi.fn(),
|
|
91
|
-
}));
|
|
92
|
-
const memStart = process?.memoryUsage?.().heapUsed;
|
|
93
|
-
const enqueueStart = now();
|
|
94
|
-
for (let i = 0; i < calls; i++) {
|
|
95
|
-
const batch = createSheetDataPatchBatch(sheetId, i * rowsPerCall, rowsPerCall, columns);
|
|
96
|
-
act(() => {
|
|
97
|
-
result.current.onBroadcastPatch(batch);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
const enqueueMs = now() - enqueueStart;
|
|
101
|
-
const applyStart = now();
|
|
102
|
-
await waitForCondition(() => {
|
|
103
|
-
const sheetData = doc.getMap("sheetDataV2").get(String(sheetId));
|
|
104
|
-
return sheetData?.length === totalRows;
|
|
105
|
-
}, timeoutMs);
|
|
106
|
-
const applyMs = now() - applyStart;
|
|
107
|
-
const sheetData = doc.getMap("sheetDataV2").get(String(sheetId));
|
|
108
|
-
const lastRow = sheetData?.get(totalRows - 1);
|
|
109
|
-
const lastValues = lastRow?.get("values");
|
|
110
|
-
const lastCell = lastValues?.get(columns - 1);
|
|
111
|
-
if (!lastCell || lastCell.value !== `R${totalRows - 1}C${columns - 1}`) {
|
|
112
|
-
throw new Error("Data loss detected: last cell value mismatch.");
|
|
113
|
-
}
|
|
114
|
-
const memEnd = process?.memoryUsage?.().heapUsed;
|
|
115
|
-
const report = {
|
|
116
|
-
sheetId,
|
|
117
|
-
calls,
|
|
118
|
-
rowsPerCall,
|
|
119
|
-
columns,
|
|
120
|
-
totalRows,
|
|
121
|
-
totalPatches,
|
|
122
|
-
enqueueMs: Math.round(enqueueMs),
|
|
123
|
-
applyMs: Math.round(applyMs),
|
|
124
|
-
transactBatches: transactSpy.mock.calls.length,
|
|
125
|
-
heapDeltaMB: typeof memStart === "number" && typeof memEnd === "number"
|
|
126
|
-
? Math.round(((memEnd - memStart) / 1024 / 1024) * 100) / 100
|
|
127
|
-
: "n/a",
|
|
128
|
-
};
|
|
129
|
-
console.table(report);
|
|
130
|
-
}, testTimeoutMs);
|
|
131
|
-
});
|