diff --git a/src/js/matrix.js b/src/js/matrix.js index f7b1cab..155576d 100644 --- a/src/js/matrix.js +++ b/src/js/matrix.js @@ -31,7 +31,7 @@ /******************************************************************************/ var µm = µMatrix; -var magicId = 'tckuvvpyvswo'; +var magicId = 'axyorpwxtmnf'; /******************************************************************************/ @@ -58,24 +58,24 @@ Matrix.GrayIndirect = Matrix.Gray | Matrix.Indirect; /******************************************************************************/ -var typeBitOffsets = { - '*': 0, - 'doc': 2, - 'cookie': 4, - 'css': 6, - 'image': 8, - 'media': 10, - 'script': 12, - 'xhr': 14, - 'frame': 16, - 'other': 18 -}; +var typeBitOffsets = new Map([ + [ '*', 0 ], + [ 'doc', 2 ], + [ 'cookie', 4 ], + [ 'css', 6 ], + [ 'image', 8 ], + [ 'media', 10 ], + [ 'script', 12 ], + [ 'xhr', 14 ], + [ 'frame', 16 ], + [ 'other', 18 ] +]); -var stateToNameMap = { - '1': 'block', - '2': 'allow', - '3': 'inherit' -}; +var stateToNameMap = new Map([ + [ 1, 'block' ], + [ 2, 'allow' ], + [ 3, 'inherit' ] +]); var nameToStateMap = { 'block': 1, @@ -84,63 +84,36 @@ var nameToStateMap = { 'inherit': 3 }; -var switchBitOffsets = { - 'matrix-off': 0, - 'https-strict': 2, - 'ua-spoof': 4, - 'referrer-spoof': 6 -}; +var switchBitOffsets = new Map([ + [ 'matrix-off', 0 ], + [ 'https-strict', 2 ], + [ 'ua-spoof', 4 ], + [ 'referrer-spoof', 6 ] +]); -var switchStateToNameMap = { - '1': 'true', - '2': 'false' -}; +var switchStateToNameMap = new Map([ + [ 1, 'true' ], + [ 2, 'false' ] +]); var nameToSwitchStateMap = { 'true': 1, - 'false': 2, - 'on': 2, // backward compatibility - 'off': 1 // backward compatibility + 'false': 2 }; /******************************************************************************/ -var columnHeaders = (function() { - var out = {}; - var i = 0; - for ( var type in typeBitOffsets ) { - if ( typeBitOffsets.hasOwnProperty(type) === false ) { - continue; - } - out[type] = i++; +Matrix.columnHeaderIndices = (function() { + var out = new Map(), + i = 0; + for ( var type of typeBitOffsets.keys() ) { + out.set(type, i++); } return out; })(); -/******************************************************************************/ -Matrix.getColumnHeaders = function() { - return columnHeaders; -}; - -/******************************************************************************/ - -var switchNames = (function() { - var out = {}; - for ( var switchName in switchBitOffsets ) { - if ( switchBitOffsets.hasOwnProperty(switchName) === false ) { - continue; - } - out[switchName] = true; - } - return out; -})(); - -/******************************************************************************/ - -Matrix.getSwitchNames = function() { - return switchNames; -}; +Matrix.switchNames = new Set(switchBitOffsets.keys()); /******************************************************************************/ @@ -208,8 +181,8 @@ var extractFirstPartyDesDomain = function(srcHostname, desHostname) { /******************************************************************************/ Matrix.prototype.reset = function() { - this.switches = {}; - this.rules = {}; + this.switches = new Map(); + this.rules = new Map(); this.rootValue = Matrix.RedIndirect; this.modifiedTime = 0; }; @@ -220,38 +193,26 @@ Matrix.prototype.reset = function() { // a live matrix. Matrix.prototype.assign = function(other) { - var k; + var k, entry; // Remove rules not in other - for ( k in this.rules ) { - if ( this.rules.hasOwnProperty(k) === false ) { - continue; - } - if ( other.rules.hasOwnProperty(k) === false ) { - delete this.rules[k]; + for ( k of this.rules.keys() ) { + if ( other.rules.has(k) === false ) { + this.rules.delete(k); } } // Remove switches not in other - for ( k in this.switches ) { - if ( this.switches.hasOwnProperty(k) === false ) { - continue; - } - if ( other.switches.hasOwnProperty(k) === false ) { - delete this.switches[k]; + for ( k of this.switches.keys() ) { + if ( other.switches.has(k) === false ) { + this.switches.delete(k); } } // Add/change rules in other - for ( k in other.rules ) { - if ( other.rules.hasOwnProperty(k) === false ) { - continue; - } - this.rules[k] = other.rules[k]; + for ( entry of other.rules ) { + this.rules.set(entry[0], entry[1]); } // Add/change switches in other - for ( k in other.switches ) { - if ( other.switches.hasOwnProperty(k) === false ) { - continue; - } - this.switches[k] = other.switches[k]; + for ( entry of other.switches ) { + this.switches.set(entry[0], entry[1]); } this.modifiedTime = other.modifiedTime; return this; @@ -264,20 +225,20 @@ Matrix.prototype.assign = function(other) { // If value is undefined, the switch is removed Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) { - var bitOffset = switchBitOffsets[switchName]; + var bitOffset = switchBitOffsets.get(switchName); if ( bitOffset === undefined ) { return false; } if ( newVal === this.evaluateSwitch(switchName, srcHostname) ) { return false; } - var bits = this.switches[srcHostname] || 0; + var bits = this.switches.get(srcHostname) || 0; bits &= ~(3 << bitOffset); bits |= newVal << bitOffset; if ( bits === 0 ) { - delete this.switches[srcHostname]; + this.switches.delete(srcHostname); } else { - this.switches[srcHostname] = bits; + this.switches.set(srcHostname, bits); } this.modifiedTime = Date.now(); return true; @@ -286,9 +247,9 @@ Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) { /******************************************************************************/ Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) { - var bitOffset = typeBitOffsets[type]; - var k = srcHostname + ' ' + desHostname; - var oldBitmap = this.rules[k]; + var bitOffset = typeBitOffsets.get(type), + k = srcHostname + ' ' + desHostname, + oldBitmap = this.rules.get(k); if ( oldBitmap === undefined ) { oldBitmap = 0; } @@ -297,9 +258,9 @@ Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) { return false; } if ( newBitmap === 0 ) { - delete this.rules[k]; + this.rules.delete(k); } else { - this.rules[k] = newBitmap; + this.rules.set(k, newBitmap); } this.modifiedTime = Date.now(); return true; @@ -357,21 +318,21 @@ Matrix.prototype.graylistCell = function(srcHostname, desHostname, type) { Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) { var key = srcHostname + ' ' + desHostname; - var bitmap = this.rules[key]; + var bitmap = this.rules.get(key); if ( bitmap === undefined ) { return 0; } - return bitmap >> typeBitOffsets[type] & 3; + return bitmap >> typeBitOffsets.get(type) & 3; }; /******************************************************************************/ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { - var bitOffset = typeBitOffsets[type]; + var bitOffset = typeBitOffsets.get(type); var s = srcHostname; var v; for (;;) { - v = this.rules[s + ' ' + desHostname]; + v = this.rules.get(s + ' ' + desHostname); if ( v !== undefined ) { v = v >> bitOffset & 3; if ( v !== 0 ) { @@ -380,9 +341,7 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { } // TODO: external rules? (for presets) s = toBroaderHostname(s); - if ( s === '' ) { - break; - } + if ( s === '' ) { break; } } // srcHostname is '*' at this point @@ -396,6 +355,7 @@ Matrix.prototype.evaluateCellZ = function(srcHostname, desHostname, type) { if ( type === 'doc' && desHostname === '*' ) { return 2; } + return 0; }; @@ -495,10 +455,7 @@ Matrix.prototype.evaluateCellZXY = function(srcHostname, desHostname, type) { Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) { var out = []; - for ( var type in typeBitOffsets ) { - if ( typeBitOffsets.hasOwnProperty(type) === false ) { - continue; - } + for ( var type of typeBitOffsets.keys() ) { out.push(this.evaluateCellZXY(srcHostname, desHostname, type)); } return out; @@ -525,7 +482,7 @@ Matrix.prototype.desHostnameFromRule = function(rule) { /******************************************************************************/ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) { - var bitOffset = switchBitOffsets[switchName]; + var bitOffset = switchBitOffsets.get(switchName); if ( bitOffset === undefined ) { return false; } @@ -536,19 +493,19 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) { if ( newState === undefined ) { newState = !state; } - var bits = this.switches[srcHostname] || 0; + var bits = this.switches.get(srcHostname) || 0; bits &= ~(3 << bitOffset); if ( bits === 0 ) { - delete this.switches[srcHostname]; + this.switches.delete(srcHostname); } else { - this.switches[srcHostname] = bits; + this.switches.set(srcHostname, bits); } this.modifiedTime = Date.now(); state = this.evaluateSwitchZ(switchName, srcHostname); if ( state === newState ) { return true; } - this.switches[srcHostname] = bits | ((newState ? 1 : 2) << bitOffset); + this.switches.set(srcHostname, bits | ((newState ? 1 : 2) << bitOffset)); return true; }; @@ -559,11 +516,11 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) { // 2 = forced default state (to override a broader non-default state) Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) { - var bits = this.switches[srcHostname] || 0; + var bits = this.switches.get(srcHostname) || 0; if ( bits === 0 ) { return 0; } - var bitOffset = switchBitOffsets[switchName]; + var bitOffset = switchBitOffsets.get(switchName); if ( bitOffset === undefined ) { return 0; } @@ -573,14 +530,14 @@ Matrix.prototype.evaluateSwitch = function(switchName, srcHostname) { /******************************************************************************/ Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) { - var bitOffset = switchBitOffsets[switchName]; + var bitOffset = switchBitOffsets.get(switchName); if ( bitOffset === undefined ) { return false; } var bits; var s = srcHostname; for (;;) { - bits = this.switches[s] || 0; + bits = this.switches.get(s) || 0; if ( bits !== 0 ) { bits = bits >> bitOffset & 3; if ( bits !== 0 ) { @@ -602,11 +559,7 @@ Matrix.prototype.evaluateSwitchZ = function(switchName, srcHostname) { Matrix.prototype.extractAllSourceHostnames = function() { var srcHostnames = {}; - var rules = this.rules; - for ( var rule in rules ) { - if ( rules.hasOwnProperty(rule) === false ) { - continue; - } + for ( var rule of this.rules.keys() ) { srcHostnames[rule.slice(0, rule.indexOf(' '))] = true; } return srcHostnames; @@ -619,11 +572,7 @@ Matrix.prototype.extractAllSourceHostnames = function() { Matrix.prototype.extractAllDestinationHostnames = function() { var desHostnames = {}; - var rules = this.rules; - for ( var rule in rules ) { - if ( rules.hasOwnProperty(rule) === false ) { - continue; - } + for ( var rule of this.rules.keys() ) { desHostnames[this.desHostnameFromRule(rule)] = true; } return desHostnames; @@ -635,41 +584,25 @@ Matrix.prototype.toString = function() { var out = []; var rule, type, switchName, val; var srcHostname, desHostname; - for ( rule in this.rules ) { - if ( this.rules.hasOwnProperty(rule) === false ) { - continue; - } + for ( rule of this.rules.keys() ) { srcHostname = this.srcHostnameFromRule(rule); desHostname = this.desHostnameFromRule(rule); - for ( type in typeBitOffsets ) { - if ( typeBitOffsets.hasOwnProperty(type) === false ) { - continue; - } + for ( type of typeBitOffsets.keys() ) { val = this.evaluateCell(srcHostname, desHostname, type); - if ( val === 0 ) { - continue; - } + if ( val === 0 ) { continue; } out.push( punycode.toUnicode(srcHostname) + ' ' + punycode.toUnicode(desHostname) + ' ' + type + ' ' + - stateToNameMap[val] + stateToNameMap.get(val) ); } } - for ( srcHostname in this.switches ) { - if ( this.switches.hasOwnProperty(srcHostname) === false ) { - continue; - } - for ( switchName in switchBitOffsets ) { - if ( switchBitOffsets.hasOwnProperty(switchName) === false ) { - continue; - } + for ( srcHostname of this.switches.keys() ) { + for ( switchName of switchBitOffsets.keys() ) { val = this.evaluateSwitch(switchName, srcHostname); - if ( val === 0 ) { - continue; - } - out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap[val]); + if ( val === 0 ) { continue; } + out.push(switchName + ': ' + srcHostname + ' ' + switchStateToNameMap.get(val)); } } return out.sort().join('\n'); @@ -744,7 +677,7 @@ Matrix.prototype.fromString = function(text, append) { if ( pos !== -1 ) { switchName = fieldVal.slice(0, pos); } - if ( switchBitOffsets.hasOwnProperty(switchName) ) { + if ( switchBitOffsets.has(switchName) ) { srcHostname = punycode.toASCII(fields[1]); // No state field: reject @@ -801,7 +734,7 @@ Matrix.prototype.fromString = function(text, append) { type = 'media'; } // Unknown type: reject - if ( typeBitOffsets.hasOwnProperty(type) === false ) { + if ( typeBitOffsets.has(type) === false ) { continue; } } else { @@ -835,17 +768,19 @@ Matrix.prototype.fromString = function(text, append) { Matrix.prototype.toSelfie = function() { return { magicId: magicId, - switches: this.switches, - rules: this.rules + switches: Array.from(this.switches), + rules: Array.from(this.rules) }; }; /******************************************************************************/ Matrix.prototype.fromSelfie = function(selfie) { - this.switches = selfie.switches; - this.rules = selfie.rules; + if ( selfie.magicId !== magicId ) { return false; } + this.switches = new Map(selfie.switches); + this.rules = new Map(selfie.rules); this.modifiedTime = Date.now(); + return true; }; /******************************************************************************/ @@ -855,10 +790,7 @@ Matrix.prototype.diff = function(other, srcHostname, desHostnames) { var desHostname, type; var switchName, i, thisVal, otherVal; for (;;) { - for ( switchName in switchBitOffsets ) { - if ( switchBitOffsets.hasOwnProperty(switchName) === false ) { - continue; - } + for ( switchName of switchBitOffsets.keys() ) { thisVal = this.evaluateSwitch(switchName, srcHostname); otherVal = other.evaluateSwitch(switchName, srcHostname); if ( thisVal !== otherVal ) { @@ -871,15 +803,10 @@ Matrix.prototype.diff = function(other, srcHostname, desHostnames) { i = desHostnames.length; while ( i-- ) { desHostname = desHostnames[i]; - for ( type in typeBitOffsets ) { - if ( typeBitOffsets.hasOwnProperty(type) === false ) { - continue; - } + for ( type of typeBitOffsets.keys() ) { thisVal = this.evaluateCell(srcHostname, desHostname, type); otherVal = other.evaluateCell(srcHostname, desHostname, type); - if ( thisVal === otherVal ) { - continue; - } + if ( thisVal === otherVal ) { continue; } out.push({ 'what': 'rule', 'src': srcHostname, @@ -909,7 +836,7 @@ Matrix.prototype.applyDiff = function(diff, from) { changed = this.setCell(action.src, action.des, action.type, val) || changed; continue; } - if ( switchBitOffsets.hasOwnProperty(action.what) ) { + if ( switchBitOffsets.has(action.what) ) { val = from.evaluateSwitch(action.what, action.src); changed = this.setSwitch(action.what, action.src, val) || changed; continue; diff --git a/src/js/messaging.js b/src/js/messaging.js index 3bb1e49..04d1018 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -130,9 +130,8 @@ var RowSnapshot = function(srcHostname, desHostname, desDomain) { }; RowSnapshot.counts = (function() { - var i = Object.keys(µm.Matrix.getColumnHeaders()).length; - var aa = new Array(i); - while ( i-- ) { + var aa = []; + for ( var i = 0, n = µm.Matrix.columnHeaderIndices.size; i < n; i++ ) { aa[i] = 0; } return aa; @@ -142,12 +141,14 @@ RowSnapshot.counts = (function() { var matrixSnapshot = function(pageStore, details) { var µmuser = µm.userSettings; + var headerIndices = µm.Matrix.columnHeaderIndices; + var r = { appVersion: vAPI.app.version, blockedCount: pageStore.requestStats.blocked.all, diff: [], domain: pageStore.pageDomain, - headers: µm.Matrix.getColumnHeaders(), + headerIndices: Array.from(headerIndices), hostname: pageStore.pageHostname, mtxContentModified: pageStore.mtxContentModifiedTime !== details.mtxContentModifiedTime, mtxCountModified: pageStore.mtxCountModifiedTime !== details.mtxCountModifiedTime, @@ -171,8 +172,6 @@ var matrixSnapshot = function(pageStore, details) { } }; - var headers = r.headers; - if ( typeof details.scope === 'string' ) { r.scope = details.scope; } else if ( µmuser.popupScopeLevel === 'site' ) { @@ -181,11 +180,7 @@ var matrixSnapshot = function(pageStore, details) { r.scope = r.domain; } - var switchNames = µm.Matrix.getSwitchNames(); - for ( var switchName in switchNames ) { - if ( switchNames.hasOwnProperty(switchName) === false ) { - continue; - } + for ( var switchName of µm.Matrix.switchNames ) { r.tSwitches[switchName] = µm.tMatrix.evaluateSwitchZ(switchName, r.scope); r.pSwitches[switchName] = µm.pMatrix.evaluateSwitchZ(switchName, r.scope); } @@ -199,7 +194,7 @@ var matrixSnapshot = function(pageStore, details) { var reqKey, reqType, reqHostname, reqDomain; var desHostname; var row, typeIndex; - var anyIndex = headers['*']; + var anyIndex = headerIndices.get('*'); var pageRequests = pageStore.requests; var reqKeys = pageRequests.getRequestKeys(); @@ -236,7 +231,7 @@ var matrixSnapshot = function(pageStore, details) { desHostname = desHostname.slice(pos + 1); } - typeIndex = headers[reqType]; + typeIndex = headerIndices.get(reqType); row = r.rows[reqHostname]; row.counts[typeIndex] += 1; diff --git a/src/js/popup.js b/src/js/popup.js index 64f7ef6..49151c3 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -224,8 +224,7 @@ function getGroupStats() { // hierarchy is white or blacklisted var pageDomain = matrixSnapshot.domain; var rows = matrixSnapshot.rows; - var columnOffsets = matrixSnapshot.headers; - var anyTypeOffset = columnOffsets['*']; + var anyTypeOffset = matrixSnapshot.headerIndices.get('*'); var hostname, domain; var row, color, count, groupIndex; var domainToGroupMap = {}; @@ -349,11 +348,11 @@ function getGroupStats() { // helpers function getTemporaryColor(hostname, type) { - return matrixSnapshot.rows[hostname].temporary[matrixSnapshot.headers[type]]; + return matrixSnapshot.rows[hostname].temporary[matrixSnapshot.headerIndices.get(type)]; } function getPermanentColor(hostname, type) { - return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headers[type]]; + return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headerIndices.get(type)]; } function addCellClass(cell, hostname, type) { @@ -429,7 +428,7 @@ function updateMatrixCounts() { var matCells = uDom('.matrix .matRow.rw > .matCell'), i = matCells.length, matRow, matCell, count, counts, - headers = matrixSnapshot.headers, + headerIndices = matrixSnapshot.headerIndices, rows = matrixSnapshot.rows, expandos; while ( i-- ) { @@ -440,7 +439,7 @@ function updateMatrixCounts() { } matRow = matCell.parentNode; counts = matRow.classList.contains('meta') ? 'totals' : 'counts'; - count = rows[expandos.hostname][counts][headers[expandos.reqType]]; + count = rows[expandos.hostname][counts][headerIndices.get(expandos.reqType)]; if ( count === expandos.count ) { continue; } expandos.count = count; matCell.textContent = count ? count : '\u00A0'; @@ -705,15 +704,15 @@ function renderMatrixCellType(cell, hostname, type, count) { function renderMatrixCellTypes(cells, hostname, countName) { var counts = matrixSnapshot.rows[hostname][countName]; - var countIndices = matrixSnapshot.headers; - renderMatrixCellType(cells.at(1), hostname, 'cookie', counts[countIndices.cookie]); - renderMatrixCellType(cells.at(2), hostname, 'css', counts[countIndices.css]); - renderMatrixCellType(cells.at(3), hostname, 'image', counts[countIndices.image]); - renderMatrixCellType(cells.at(4), hostname, 'media', counts[countIndices.media]); - renderMatrixCellType(cells.at(5), hostname, 'script', counts[countIndices.script]); - renderMatrixCellType(cells.at(6), hostname, 'xhr', counts[countIndices.xhr]); - renderMatrixCellType(cells.at(7), hostname, 'frame', counts[countIndices.frame]); - renderMatrixCellType(cells.at(8), hostname, 'other', counts[countIndices.other]); + var headerIndices = matrixSnapshot.headerIndices; + renderMatrixCellType(cells.at(1), hostname, 'cookie', counts[headerIndices.get('cookie')]); + renderMatrixCellType(cells.at(2), hostname, 'css', counts[headerIndices.get('css')]); + renderMatrixCellType(cells.at(3), hostname, 'image', counts[headerIndices.get('image')]); + renderMatrixCellType(cells.at(4), hostname, 'media', counts[headerIndices.get('media')]); + renderMatrixCellType(cells.at(5), hostname, 'script', counts[headerIndices.get('script')]); + renderMatrixCellType(cells.at(6), hostname, 'xhr', counts[headerIndices.get('xhr')]); + renderMatrixCellType(cells.at(7), hostname, 'frame', counts[headerIndices.get('frame')]); + renderMatrixCellType(cells.at(8), hostname, 'other', counts[headerIndices.get('other')]); } /******************************************************************************/ @@ -760,36 +759,37 @@ function renderMatrixMetaCellType(cell, count) { } function makeMatrixMetaRow(totals) { - var typeOffsets = matrixSnapshot.headers; - var matrixRow = createMatrixRow().at(0).addClass('ro'); - var cells = matrixRow.descendants('.matCell'); - var contents = cells.at(0).addClass('t81').contents(); - var expandos = expandosFromNode(cells.nodeAt(0)); + var headerIndices = matrixSnapshot.headerIndices, + matrixRow = createMatrixRow().at(0).addClass('ro'), + cells = matrixRow.descendants('.matCell'), + contents = cells.at(0).addClass('t81').contents(), + expandos = expandosFromNode(cells.nodeAt(0)); expandos.hostname = ''; expandos.reqType = '*'; contents.nodeAt(0).textContent = ' '; contents.nodeAt(1).textContent = blacklistedHostnamesLabel.replace( '{{count}}', - totals[typeOffsets['*']].toLocaleString() + totals[headerIndices.get('*')].toLocaleString() ); - renderMatrixMetaCellType(cells.at(1), totals[typeOffsets.cookie]); - renderMatrixMetaCellType(cells.at(2), totals[typeOffsets.css]); - renderMatrixMetaCellType(cells.at(3), totals[typeOffsets.image]); - renderMatrixMetaCellType(cells.at(4), totals[typeOffsets.media]); - renderMatrixMetaCellType(cells.at(5), totals[typeOffsets.script]); - renderMatrixMetaCellType(cells.at(6), totals[typeOffsets.xhr]); - renderMatrixMetaCellType(cells.at(7), totals[typeOffsets.frame]); - renderMatrixMetaCellType(cells.at(8), totals[typeOffsets.other]); + renderMatrixMetaCellType(cells.at(1), totals[headerIndices.get('cookie')]); + renderMatrixMetaCellType(cells.at(2), totals[headerIndices.get('css')]); + renderMatrixMetaCellType(cells.at(3), totals[headerIndices.get('image')]); + renderMatrixMetaCellType(cells.at(4), totals[headerIndices.get('media')]); + renderMatrixMetaCellType(cells.at(5), totals[headerIndices.get('script')]); + renderMatrixMetaCellType(cells.at(6), totals[headerIndices.get('xhr')]); + renderMatrixMetaCellType(cells.at(7), totals[headerIndices.get('frame')]); + renderMatrixMetaCellType(cells.at(8), totals[headerIndices.get('other')]); return matrixRow; } /******************************************************************************/ function computeMatrixGroupMetaStats(group) { - var headers = matrixSnapshot.headers; - var n = Object.keys(headers).length; - var totals = new Array(n); - var i = n; + var headerIndices = matrixSnapshot.headerIndices, + anyTypeIndex = headerIndices.get('*'), + n = headerIndices.size, + totals = new Array(n), + i = n; while ( i-- ) { totals[i] = 0; } @@ -802,7 +802,7 @@ function computeMatrixGroupMetaStats(group) { if ( group.hasOwnProperty(row.domain) === false ) { continue; } - if ( row.counts[headers['*']] === 0 ) { + if ( row.counts[anyTypeIndex] === 0 ) { continue; } totals[0] += 1; @@ -1367,6 +1367,13 @@ var onMatrixSnapshotReady = function(response) { var matrixSnapshotPoller = (function() { var timer = null; + var preprocessMatrixSnapshot = function(snapshot) { + if ( Array.isArray(snapshot.headerIndices) ) { + snapshot.headerIndices = new Map(snapshot.headerIndices); + } + return snapshot; + }; + var processPollResult = function(response) { if ( typeof response !== 'object' ) { return; @@ -1379,7 +1386,8 @@ var matrixSnapshotPoller = (function() { ) { return; } - matrixSnapshot = response; + matrixSnapshot = preprocessMatrixSnapshot(response); + if ( response.mtxContentModified ) { makeMenu(); return; @@ -1454,7 +1462,7 @@ var matrixSnapshotPoller = (function() { var snapshotFetched = function(response) { if ( typeof response === 'object' ) { - matrixSnapshot = response; + matrixSnapshot = preprocessMatrixSnapshot(response); } onMatrixSnapshotReady(response); pollAsync();