mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 01:27:12 +02:00
code review: benefit from ES6 Set() in content script
fall back on legacy browser-specific polyfill code if required.
This commit is contained in:
parent
4c714cb11c
commit
cd81f866b9
@ -67,6 +67,114 @@ if ( vAPI.sessionId ) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Support minimally working Set() for legacy Chromium.
|
||||
|
||||
if ( self.Set instanceof Function ) {
|
||||
self.createSet = function() {
|
||||
return new Set();
|
||||
};
|
||||
} else {
|
||||
self.createSet = (function() {
|
||||
//console.log('Polyfilling for ES6-like Set().');
|
||||
var PrimitiveSet = function() {
|
||||
this.clear();
|
||||
};
|
||||
PrimitiveSet.prototype = {
|
||||
add: function(k) {
|
||||
if ( this._set[k] === undefined ) {
|
||||
this._set[k] = true;
|
||||
this.size += 1;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
clear: function() {
|
||||
this._set = Object.create(null);
|
||||
this.size = 0;
|
||||
this._values = undefined;
|
||||
this._i = undefined;
|
||||
this.value = undefined;
|
||||
this.done = true;
|
||||
},
|
||||
delete: function(k) {
|
||||
if ( this._set[k] === undefined ) { return false; }
|
||||
delete this._set[k];
|
||||
this.size -= 1;
|
||||
return true;
|
||||
},
|
||||
has: function(k) {
|
||||
return this._set[k] !== undefined;
|
||||
},
|
||||
next: function() {
|
||||
if ( this._i < this.size ) {
|
||||
this.value = this._values[this._i++];
|
||||
} else {
|
||||
this._values = undefined;
|
||||
this.value = undefined;
|
||||
this.done = true;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
polyfill: true,
|
||||
values: function() {
|
||||
this._values = Object.keys(this._set);
|
||||
this._i = 0;
|
||||
this.value = undefined;
|
||||
this.done = false;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
var ReferenceSet = function() {
|
||||
this.clear();
|
||||
};
|
||||
ReferenceSet.prototype = {
|
||||
add: function(k) {
|
||||
if ( this._set.indexOf(k) === -1 ) {
|
||||
this._set.push(k);
|
||||
}
|
||||
},
|
||||
clear: function() {
|
||||
this._set = [];
|
||||
this._i = 0;
|
||||
this.value = undefined;
|
||||
this.done = true;
|
||||
},
|
||||
delete: function(k) {
|
||||
var pos = this._set.indexOf(k);
|
||||
if ( pos === -1 ) { return false; }
|
||||
this._set.splice(pos, 1);
|
||||
return true;
|
||||
},
|
||||
has: function(k) {
|
||||
return this._set.indexOf(k) !== -1;
|
||||
},
|
||||
next: function() {
|
||||
if ( this._i === this._set.length ) {
|
||||
this.value = undefined;
|
||||
this.done = true;
|
||||
} else {
|
||||
this.value = this._set[this._i];
|
||||
this._i += 1;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
polyfill: true,
|
||||
values: function() {
|
||||
this._i = 0;
|
||||
this.done = false;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
Object.defineProperty(ReferenceSet.prototype, 'size', {
|
||||
get: function() { return this._set.length; }
|
||||
});
|
||||
return function(type) {
|
||||
return type === 'object' ? new ReferenceSet() : new PrimitiveSet();
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var referenceCounter = 0;
|
||||
|
||||
vAPI.lock = function() {
|
||||
|
@ -49,6 +49,46 @@ var vAPI = self.vAPI = self.vAPI || {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Support minimally working Set() for legacy Firefox: iterator for legacy
|
||||
// Set() does not work like the one for standard ES6 Set().
|
||||
|
||||
if ( self.Set.prototype.iterator instanceof Function === false ) {
|
||||
self.createSet = function() {
|
||||
return new Set();
|
||||
};
|
||||
} else {
|
||||
self.createSet = (function() {
|
||||
//console.log('Patching non-ES6 Set() to be more ES6-like.');
|
||||
var values = function() {
|
||||
this._valueIter = this.prototype.values();
|
||||
this.value = undefined;
|
||||
this.done = false;
|
||||
return this;
|
||||
};
|
||||
var next = function() {
|
||||
try {
|
||||
this.value = this._valueIter.next();
|
||||
} catch (ex) {
|
||||
this._valueIter = undefined;
|
||||
this.value = undefined;
|
||||
this.done = true;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
return function() {
|
||||
var r = new Set();
|
||||
r._valueIter = undefined;
|
||||
r.value = undefined;
|
||||
r.done = false;
|
||||
r.values = values.bind(r);
|
||||
r.next = next.bind(r);
|
||||
return r;
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var referenceCounter = 0;
|
||||
|
||||
vAPI.lock = function() {
|
||||
|
@ -19,6 +19,8 @@
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
/* global createSet */
|
||||
|
||||
'use strict';
|
||||
|
||||
/*******************************************************************************
|
||||
@ -100,50 +102,6 @@ vAPI.domFilterer = (function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if ( typeof self.Set !== 'function' ) {
|
||||
self.Set = function() {
|
||||
this._set = [];
|
||||
this._i = 0;
|
||||
this.value = undefined;
|
||||
};
|
||||
self.Set.prototype = {
|
||||
polyfill: true,
|
||||
clear: function() {
|
||||
this._set = [];
|
||||
},
|
||||
add: function(k) {
|
||||
if ( this._set.indexOf(k) === -1 ) {
|
||||
this._set.push(k);
|
||||
}
|
||||
},
|
||||
delete: function(k) {
|
||||
var pos = this._set.indexOf(k);
|
||||
if ( pos !== -1 ) {
|
||||
this._set.splice(pos, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
has: function(k) {
|
||||
return this._set.indexOf(k) !== -1;
|
||||
},
|
||||
values: function() {
|
||||
this._i = 0;
|
||||
return this;
|
||||
},
|
||||
next: function() {
|
||||
this.value = this._set[this._i];
|
||||
this._i += 1;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
Object.defineProperty(self.Set.prototype, 'size', {
|
||||
get: function() { return this._set.length; }
|
||||
});
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var shadowId = document.documentElement.shadowRoot !== undefined ?
|
||||
vAPI.randomToken():
|
||||
undefined;
|
||||
@ -157,8 +115,8 @@ var jobQueue = [
|
||||
|
||||
var reParserEx = /:(?:matches-css|has|style|xpath)\(.+?\)$/;
|
||||
|
||||
var allExceptions = Object.create(null),
|
||||
allSelectors = Object.create(null),
|
||||
var allExceptions = createSet(),
|
||||
allSelectors = createSet(),
|
||||
commitTimer = null,
|
||||
stagedNodes = [],
|
||||
matchesProp = vAPI.matchesProp,
|
||||
@ -168,7 +126,7 @@ var allExceptions = Object.create(null),
|
||||
// Set() is used to implement this functionality.
|
||||
|
||||
var complexSelectorsOldResultSet,
|
||||
complexSelectorsCurrentResultSet = new Set();
|
||||
complexSelectorsCurrentResultSet = createSet('object');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -308,7 +266,7 @@ var domFilterer = {
|
||||
|
||||
addExceptions: function(aa) {
|
||||
for ( var i = 0, n = aa.length; i < n; i++ ) {
|
||||
allExceptions[aa[i]] = true;
|
||||
allExceptions.add(aa[i]);
|
||||
}
|
||||
},
|
||||
|
||||
@ -324,10 +282,10 @@ var domFilterer = {
|
||||
// xpath/hide
|
||||
|
||||
addSelector: function(s) {
|
||||
if ( allSelectors[s] || allExceptions[s] ) {
|
||||
if ( allSelectors.has(s) || allExceptions.has(s) ) {
|
||||
return;
|
||||
}
|
||||
allSelectors[s] = true;
|
||||
allSelectors.add(s);
|
||||
var sel0 = s, sel1 = '';
|
||||
if ( s.charCodeAt(s.length - 1) === 0x29 ) {
|
||||
var parts = reParserEx.exec(s);
|
||||
@ -445,7 +403,7 @@ var domFilterer = {
|
||||
|
||||
// Complex selectors: non-incremental.
|
||||
complexSelectorsOldResultSet = complexSelectorsCurrentResultSet;
|
||||
complexSelectorsCurrentResultSet = new Set();
|
||||
complexSelectorsCurrentResultSet = createSet('object');
|
||||
|
||||
// Stock job 3 = complex css selectors/hide
|
||||
// The handling of these can be considered optional, since they are
|
||||
@ -1193,7 +1151,7 @@ vAPI.domSurveyor = (function() {
|
||||
cosmeticSurveyingMissCount = 0,
|
||||
highGenerics = null,
|
||||
lowGenericSelectors = [],
|
||||
queriedSelectors = Object.create(null),
|
||||
queriedSelectors = createSet(),
|
||||
surveyCost = 0;
|
||||
|
||||
// Handle main process' response.
|
||||
@ -1454,28 +1412,19 @@ vAPI.domSurveyor = (function() {
|
||||
v = node.id;
|
||||
if ( v !== '' && typeof v === 'string' ) {
|
||||
v = '#' + v.trim();
|
||||
if ( v !== '#' && qq[v] === undefined ) {
|
||||
ll.push(v);
|
||||
qq[v] = true;
|
||||
}
|
||||
if ( v !== '#' && !qq.has(v) ) { ll.push(v); qq.add(v); }
|
||||
}
|
||||
vv = node.className;
|
||||
if ( vv === '' || typeof vv !== 'string' ) { continue; }
|
||||
if ( /\s/.test(vv) === false ) {
|
||||
v = '.' + vv;
|
||||
if ( qq[v] === undefined ) {
|
||||
ll.push(v);
|
||||
qq[v] = true;
|
||||
}
|
||||
if ( !qq.has(v) ) { ll.push(v); qq.add(v); }
|
||||
} else {
|
||||
vv = node.classList;
|
||||
j = vv.length;
|
||||
while ( j-- ) {
|
||||
v = '.' + vv[j];
|
||||
if ( qq[v] === undefined ) {
|
||||
ll.push(v);
|
||||
qq[v] = true;
|
||||
}
|
||||
if ( !qq.has(v) ) { ll.push(v); qq.add(v); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user