From 48d9a0fd2667029f4888765c558afde02c6d0adf Mon Sep 17 00:00:00 2001 From: gorhill Date: Wed, 15 Mar 2017 16:30:48 -0400 Subject: [PATCH] fix #711 --- src/js/popup.js | 239 ++++++++++++++++++++++++++++-------------------- src/js/udom.js | 6 +- 2 files changed, 143 insertions(+), 102 deletions(-) diff --git a/src/js/popup.js b/src/js/popup.js index 67f79e0..2e72277 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1,7 +1,7 @@ /******************************************************************************* uMatrix - a Chromium browser extension to black/white list requests. - Copyright (C) 2014-2016 Raymond Hill + Copyright (C) 2014-2017 Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,13 +22,13 @@ /* global punycode, vAPI, uDom */ /* jshint esnext: true, bitwise: false */ +'use strict'; + /******************************************************************************/ /******************************************************************************/ (function() { -'use strict'; - /******************************************************************************/ /******************************************************************************/ @@ -67,6 +67,29 @@ var matrixHeaderPrettyNames = { var firstPartyLabel = ''; var blacklistedHostnamesLabel = ''; +var nodeToExpandosMap = (function() { + if ( typeof window.WeakMap === 'function' ) { + return new window.WeakMap(); + } +})(); + +var expandosFromNode = function(node) { + if ( + node instanceof HTMLElement === false && + typeof node.nodeAt === 'function' + ) { + node = node.nodeAt(0); + } + if ( nodeToExpandosMap ) { + var expandos = nodeToExpandosMap.get(node); + if ( expandos === undefined ) { + nodeToExpandosMap.set(node, (expandos = Object.create(null))); + } + return expandos; + } + return node; +}; + var messager = vAPI.messaging.channel('popup.js'); /******************************************************************************/ @@ -263,9 +286,11 @@ function getPermanentColor(hostname, type) { return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headers[type]]; } -function getCellClass(hostname, type) { - return 't' + getTemporaryColor(hostname, type).toString(16) + - ' p' + getPermanentColor(hostname, type).toString(16); +function addCellClass(cell, hostname, type) { + var cl = cell.classList; + cell.classList.add('matCell'); + cell.classList.add('t' + getTemporaryColor(hostname, type).toString(16)); + cell.classList.add('p' + getPermanentColor(hostname, type).toString(16)); } /******************************************************************************/ @@ -313,11 +338,11 @@ function toggleMainCollapseState(uelem) { function toggleSpecificCollapseState(uelem) { // Remember collapse state forever, but only if it is different // from main collapse switch. - var section = uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'); - var domain = section.prop('domain'); - var collapsed = section.hasClass('collapsed'); - var mainCollapseState = getUISetting('popupCollapseDomains') === true; - var specificCollapseStates = getUISetting('popupCollapseSpecificDomains') || {}; + var section = uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'), + domain = expandosFromNode(section).domain, + collapsed = section.hasClass('collapsed'), + mainCollapseState = getUISetting('popupCollapseDomains') === true, + specificCollapseStates = getUISetting('popupCollapseSpecificDomains') || {}; if ( collapsed !== mainCollapseState ) { specificCollapseStates[domain] = collapsed; setUISetting('popupCollapseSpecificDomains', specificCollapseStates); @@ -332,26 +357,23 @@ function toggleSpecificCollapseState(uelem) { // Update count value of matrix cells(s) function updateMatrixCounts() { - var matCells = uDom('.matrix .matRow.rw > .matCell'); - var i = matCells.length; - var matRow, matCell, count, counts; - var headers = matrixSnapshot.headers; - var rows = matrixSnapshot.rows; + var matCells = uDom('.matrix .matRow.rw > .matCell'), + i = matCells.length, + matRow, matCell, count, counts, + headers = matrixSnapshot.headers, + rows = matrixSnapshot.rows, + expandos; while ( i-- ) { matCell = matCells.nodeAt(i); - if ( matCell.hostname === '*' ) { - continue; - } - if ( matCell.reqType === '*' ) { + expandos = expandosFromNode(matCell); + if ( expandos.hostname === '*' || expandos.reqType === '*' ) { continue; } matRow = matCell.parentNode; counts = matRow.classList.contains('meta') ? 'totals' : 'counts'; - count = rows[matCell.hostname][counts][headers[matCell.reqType]]; - if ( count === matCell.count) { - continue; - } - matCell.count = count; + count = rows[expandos.hostname][counts][headers[expandos.reqType]]; + if ( count === expandos.count ) { continue; } + expandos.count = count; matCell.textContent = count ? count : '\u00A0'; } } @@ -362,12 +384,13 @@ function updateMatrixCounts() { // Color changes when rules change function updateMatrixColors() { - var cells = uDom('.matrix .matRow.rw > .matCell').removeClass(); - var i = cells.length; - var cell; + var cells = uDom('.matrix .matRow.rw > .matCell').removeClass(), + i = cells.length, + cell, expandos; while ( i-- ) { cell = cells.nodeAt(i); - cell.className = 'matCell ' + getCellClass(cell.hostname, cell.reqType); + expandos = expandosFromNode(cell); + addCellClass(cell, expandos.hostname, expandos.reqType); } resizePopup(); } @@ -418,9 +441,10 @@ function getCellAction(hostname, type, leaning) { function handleFilter(button, leaning) { // our parent cell knows who we are - var cell = button.ancestors('div.matCell'); - var type = cell.prop('reqType'); - var desHostname = cell.prop('hostname'); + var cell = button.ancestors('div.matCell'), + expandos = expandosFromNode(cell), + type = expandos.reqType, + desHostname = expandos.hostname; // https://github.com/gorhill/uMatrix/issues/24 // No hostname can happen -- like with blacklist meta row if ( desHostname === '' ) { @@ -515,53 +539,63 @@ var createMatrixRow = function() { function renderMatrixHeaderRow() { var matHead = uDom('#matHead.collapsible'); matHead.toggleClass('collapsed', getUISetting('popupCollapseDomains') === true); - var cells = matHead.descendants('.matCell'); - cells.at(0) - .prop('reqType', '*') - .prop('hostname', '*') - .addClass(getCellClass('*', '*')); - cells.at(1) - .prop('reqType', 'cookie') - .prop('hostname', '*') - .addClass(getCellClass('*', 'cookie')); - cells.at(2) - .prop('reqType', 'css') - .prop('hostname', '*') - .addClass(getCellClass('*', 'css')); - cells.at(3) - .prop('reqType', 'image') - .prop('hostname', '*') - .addClass(getCellClass('*', 'image')); - cells.at(4) - .prop('reqType', 'plugin') - .prop('hostname', '*') - .addClass(getCellClass('*', 'plugin')); - cells.at(5) - .prop('reqType', 'script') - .prop('hostname', '*') - .addClass(getCellClass('*', 'script')); - cells.at(6) - .prop('reqType', 'xhr') - .prop('hostname', '*') - .addClass(getCellClass('*', 'xhr')); - cells.at(7) - .prop('reqType', 'frame') - .prop('hostname', '*') - .addClass(getCellClass('*', 'frame')); - cells.at(8) - .prop('reqType', 'other') - .prop('hostname', '*') - .addClass(getCellClass('*', 'other')); + var cells = matHead.descendants('.matCell'), cell, expandos; + cell = cells.nodeAt(0); + expandos = expandosFromNode(cell); + expandos.reqType = '*'; + expandos.hostname = '*'; + addCellClass(cell, '*', '*'); + cell = cells.nodeAt(1); + expandos = expandosFromNode(cell); + expandos.reqType = 'cookie'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'cookie'); + cell = cells.nodeAt(2); + expandos = expandosFromNode(cell); + expandos.reqType = 'css'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'css'); + cell = cells.nodeAt(3); + expandos = expandosFromNode(cell); + expandos.reqType = 'image'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'image'); + cell = cells.nodeAt(4); + expandos = expandosFromNode(cell); + expandos.reqType = 'plugin'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'plugin'); + cell = cells.nodeAt(5); + expandos = expandosFromNode(cell); + expandos.reqType = 'script'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'script'); + cell = cells.nodeAt(6); + expandos = expandosFromNode(cell); + expandos.reqType = 'xhr'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'xhr'); + cell = cells.nodeAt(7); + expandos = expandosFromNode(cell); + expandos.reqType = 'frame'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'frame'); + cell = cells.nodeAt(8); + expandos = expandosFromNode(cell); + expandos.reqType = 'other'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'other'); uDom('#matHead .matRow').css('display', ''); } /******************************************************************************/ function renderMatrixCellDomain(cell, domain) { - var contents = cell.prop('reqType', '*') - .prop('hostname', domain) - .addClass(getCellClass(domain, '*')) - .contents(); + var expandos = expandosFromNode(cell); + expandos.hostname = domain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), domain, '*'); + var contents = cell.contents(); contents.nodeAt(0).textContent = domain === '1st-party' ? firstPartyLabel : punycode.toUnicode(domain); @@ -569,28 +603,31 @@ function renderMatrixCellDomain(cell, domain) { } function renderMatrixCellSubdomain(cell, domain, subomain) { - var contents = cell.prop('reqType', '*') - .prop('hostname', subomain) - .addClass(getCellClass(subomain, '*')) - .contents(); + var expandos = expandosFromNode(cell); + expandos.hostname = subomain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), subomain, '*'); + var contents = cell.contents(); contents.nodeAt(0).textContent = punycode.toUnicode(subomain.slice(0, subomain.lastIndexOf(domain)-1)) + '.'; contents.nodeAt(1).textContent = punycode.toUnicode(domain); } function renderMatrixMetaCellDomain(cell, domain) { - var contents = cell.prop('reqType', '*') - .prop('hostname', domain) - .addClass(getCellClass(domain, '*')) - .contents(); + var expandos = expandosFromNode(cell); + expandos.hostname = domain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), domain, '*'); + var contents = cell.contents(); contents.nodeAt(0).textContent = '\u2217.' + punycode.toUnicode(domain); contents.nodeAt(1).textContent = ' '; } function renderMatrixCellType(cell, hostname, type, count) { - cell.prop('reqType', type) - .prop('hostname', hostname) - .prop('count', count) - .addClass(getCellClass(hostname, type)); + var expandos = expandosFromNode(cell); + expandos.hostname = hostname; + expandos.reqType = type; + expandos.count = count; + addCellClass(cell.nodeAt(0), hostname, type); if ( count ) { cell.text(count); } else { @@ -642,10 +679,11 @@ function makeMatrixMetaRowDomain(domain) { function renderMatrixMetaCellType(cell, count) { // https://github.com/gorhill/uMatrix/issues/24 // Don't forget to reset cell properties - cell.addClass('t1') - .prop('reqType', '') - .prop('hostname', '') - .prop('count', count); + var expandos = expandosFromNode(cell); + expandos.hostname = ''; + expandos.reqType = ''; + expandos.count = count; + cell.addClass('t1'); if ( count ) { cell.text(count); } else { @@ -658,7 +696,9 @@ function makeMatrixMetaRow(totals) { var matrixRow = createMatrixRow().at(0).addClass('ro'); var cells = matrixRow.descendants('.matCell'); var contents = cells.at(0).addClass('t81').contents(); - cells.at(0).prop('reqType', '*').prop('hostname', ''); + var expandos = expandosFromNode(cells.nodeAt(0)); + expandos.hostname = ''; + expandos.reqType = '*'; contents.nodeAt(0).textContent = ' '; contents.nodeAt(1).textContent = blacklistedHostnamesLabel.replace( '{{count}}', @@ -731,7 +771,8 @@ function makeMatrixGroup0SectionDomain() { } function makeMatrixGroup0Section() { - var domainDiv = createMatrixSection().prop('domain', '1st-party'); + var domainDiv = createMatrixSection(); + expandosFromNode(domainDiv).domain = '1st-party'; makeMatrixGroup0SectionDomain().appendTo(domainDiv); return domainDiv; } @@ -766,8 +807,8 @@ function makeMatrixGroup1SectionMetaDomain(domain) { function makeMatrixGroup1Section(hostnames) { var domain = hostnames[0]; var domainDiv = createMatrixSection() - .toggleClass('collapsed', getCollapseState(domain)) - .prop('domain', domain); + .toggleClass('collapsed', getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; if ( hostnames.length > 1 ) { makeMatrixGroup1SectionMetaDomain(domain) .appendTo(domainDiv); @@ -814,8 +855,8 @@ function makeMatrixGroup2SectionMetaDomain(domain) { function makeMatrixGroup2Section(hostnames) { var domain = hostnames[0]; var domainDiv = createMatrixSection() - .toggleClass('collapsed', getCollapseState(domain)) - .prop('domain', domain); + .toggleClass('collapsed', getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; if ( hostnames.length > 1 ) { makeMatrixGroup2SectionMetaDomain(domain).appendTo(domainDiv); } @@ -862,8 +903,8 @@ function makeMatrixGroup3SectionMetaDomain(domain) { function makeMatrixGroup3Section(hostnames) { var domain = hostnames[0]; var domainDiv = createMatrixSection() - .toggleClass('collapsed', getCollapseState(domain)) - .prop('domain', domain); + .toggleClass('collapsed', getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; if ( hostnames.length > 1 ) { makeMatrixGroup3SectionMetaDomain(domain).appendTo(domainDiv); } @@ -905,8 +946,8 @@ function makeMatrixGroup4SectionSubomain(domain, subdomain) { function makeMatrixGroup4Section(hostnames) { var domain = hostnames[0]; - var domainDiv = createMatrixSection() - .prop('domain', domain); + var domainDiv = createMatrixSection(); + expandosFromNode(domainDiv).domain = domain; makeMatrixGroup4SectionDomain(domain) .appendTo(domainDiv); for ( var i = 1; i < hostnames.length; i++ ) { diff --git a/src/js/udom.js b/src/js/udom.js index ea6757f..3ac2f97 100644 --- a/src/js/udom.js +++ b/src/js/udom.js @@ -1,7 +1,7 @@ /******************************************************************************* µBlock - a browser extension to block requests. - Copyright (C) 2014 Raymond Hill + Copyright (C) 2014-2017 Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,8 @@ /* global DOMTokenList */ /* exported uDom */ +'use strict'; + /******************************************************************************/ // It's just a silly, minimalist DOM framework: this allows me to not rely @@ -32,8 +34,6 @@ var uDom = (function() { -'use strict'; - /******************************************************************************/ var DOMList = function() {