mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-12 10:19:42 +02:00
fix(preview): bound what ExcelJS expands during XLSX admission
ExcelJS 4.4.0 expands three constructs into one object per cell or column at load time, so a few KB admitted as one cell could cost a gigabyte: - a <mergeCell> now costs its full area against the per-sheet and total cell caps, and a ref that does not parse is refused - a <col> whose min or max is past 16384 is refused - the worker loads with ignoreNodes: ['dataValidations']; the preview never shows validations, and a whole-column dropdown took 5 s The XML counter now scans up to the last complete tag and carries the rest, so a merge or col tag cut by an inflate-chunk edge is read whole. A central-directory compressedSize that runs past the file is refused, since the ratio cap divides by it. The renderer and core axis offsets use prefix sums with a binary search instead of walking every override per call.
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
(function initSpreadsheetPreview(global) {
|
||||
'use strict';
|
||||
|
||||
const SPREADSHEET_ASSET_VERSION = '91b615278d5b';
|
||||
const SPREADSHEET_ASSET_VERSION = '078d54b1055a';
|
||||
const MAX_PREVIEW_BYTES = 10 * 1024 * 1024;
|
||||
const DEFAULT_TIMEOUT_MS = 20000;
|
||||
const MAX_SCROLL_PX = 8000000;
|
||||
@@ -82,14 +82,37 @@
|
||||
return metadata?.sheets.find((sheet) => String(sheet.id) === String(activeSheetId));
|
||||
}
|
||||
|
||||
// Prefix sums per override list, built once per sheet's axis: renderTile
|
||||
// asks for several offsets per cell, so a linear walk over every override
|
||||
// (one per row on a sheet with explicit heights) made each tile O(n) per cell.
|
||||
const axisDeltas = new WeakMap();
|
||||
|
||||
function overrideDeltas(overrides, defaultSize) {
|
||||
let entry = axisDeltas.get(overrides);
|
||||
if (!entry || entry.defaultSize !== defaultSize) {
|
||||
const deltas = [];
|
||||
let delta = 0;
|
||||
for (const [, size] of overrides) {
|
||||
delta += size - defaultSize;
|
||||
deltas.push(delta);
|
||||
}
|
||||
entry = { defaultSize, deltas };
|
||||
axisDeltas.set(overrides, entry);
|
||||
}
|
||||
return entry.deltas;
|
||||
}
|
||||
|
||||
function axisOffset(count, defaultSize, overrides, index) {
|
||||
const bounded = Math.max(1, Math.min(count + 1, index));
|
||||
let value = (bounded - 1) * defaultSize;
|
||||
for (const [overrideIndex, size] of overrides || []) {
|
||||
if (overrideIndex >= bounded) break;
|
||||
value += size - defaultSize;
|
||||
const list = overrides || [];
|
||||
let low = 0;
|
||||
let high = list.length;
|
||||
while (low < high) {
|
||||
const mid = (low + high) >> 1;
|
||||
if (list[mid][0] < bounded) low = mid + 1;
|
||||
else high = mid;
|
||||
}
|
||||
return value;
|
||||
return (bounded - 1) * defaultSize + (low ? overrideDeltas(list, defaultSize)[low - 1] : 0);
|
||||
}
|
||||
|
||||
function axisIndex(count, defaultSize, overrides, offset) {
|
||||
|
||||
Reference in New Issue
Block a user