diff --git a/app.js b/app.js index b8c62279..153da14d 100644 --- a/app.js +++ b/app.js @@ -952,6 +952,12 @@ function createWarningBadge(warning) { const persistentOwnerColorMap = new Map(); +// ⚡ Bolt: Cache unattached template nodes and instantiate via cloneNode(false) +// instead of document.createElement() to reduce JS-to-C++ DOM instantiation +// overhead in O(N) table rendering loops. +const ownerBadgeTemplate = document.createElement('span'); +ownerBadgeTemplate.className = 'owner-badge'; + function createOwnerCellContent(owner) { if (!owner) { return createEmptyCell(); @@ -961,18 +967,20 @@ function createOwnerCellContent(owner) { persistentOwnerColorMap.set(owner, OWNER_COLORS[persistentOwnerColorMap.size % OWNER_COLORS.length]); } - const badge = document.createElement('span'); - badge.className = 'owner-badge'; + const badge = ownerBadgeTemplate.cloneNode(false); badge.style.background = persistentOwnerColorMap.get(owner); badge.textContent = owner; return badge; } +// ⚡ Bolt: Cache status badge template to reduce GC pressure and instantiation overhead +const statusBadgeTemplate = document.createElement('span'); + function createStatusCellContent(progressState) { if (!progressState.label) { return createEmptyCell(); } - const badge = document.createElement('span'); + const badge = statusBadgeTemplate.cloneNode(false); badge.className = `status-badge ${progressState.className}`; badge.textContent = progressState.label; if (progressState.description) { diff --git a/cloud-sync.js b/cloud-sync.js index 7e44932b..cd49ec71 100644 --- a/cloud-sync.js +++ b/cloud-sync.js @@ -740,8 +740,13 @@ function openReportModal() { // hand-edited files ever matter. export function parseMsProjectXml(xml) { const tag = (block, name) => { - const m = block.match(new RegExp(`<${name}>([^<]*)`)); - return m ? m[1].trim() : ''; + const openTag = `<${name}>`; + const closeTag = ``; + const start = block.indexOf(openTag); + if (start === -1) return ''; + const end = block.indexOf(closeTag, start + openTag.length); + if (end === -1) return ''; + return block.substring(start + openTag.length, end).trim(); }; const unescape = (s) => s .replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')