30
loading...
This website collects cookies to deliver better user experience
async function getBlockedSelectors(allSelectors) {
// A storage for the test elements
const elements = new Array(allSelectors.length)
const blockedSelectors = []
try {
// First create all elements that can be blocked
for (let i = 0; i < allSelectors.length; ++i) {
const container = document.createElement('div')
const element = selectorToElement(allSelectors[i])
elements[i] = element
container.appendChild(element)
document.body.appendChild(container)
}
// Then wait for the ad blocker to hide the element
await new Promise(resolve => setTimeout(resolve, 10))
// Then check which of the elements are blocked
for (let i = 0; i < allSelectors.length; ++i) {
if (!elements[i].offsetParent) {
blockedSelectors.push(allSelectors[i])
}
}
} finally {
// Then remove the elements
for (const element of elements) {
if (element) {
element.parentNode.remove()
}
}
}
return blockedSelectors
}
// Creates a DOM element that matches the given selector
function selectorToElement(selector) {
// See the implementation at https://bit.ly/3yg1zhX
}
getBlockedSelectors(['.advertisement', 'img[alt="Promo"]'])
.then(blockedSelectors => {
console.log(blockedSelectors)
})
const uniqueSelectorsOfFilters = {
easyList: '[lazy-ad="leftthin_banner"]',
fanboyAnnoyances: '#feedback-tab'
}
async function getActiveFilters(uniqueSelectors) {
const selectorArray = Object.values(uniqueSelectors)
// See the snippet above
const blockedSelectors = new Set(
await getBlockedSelectors(selectorArray)
)
return Object.keys(uniqueSelectors)
.filter(filterName => {
const selector = uniqueSelectors[filterName]
return blockedSelectors.has(selector)
})
}
getActiveFilters(uniqueSelectorsOfFilters)
.then(activeFilters => {
console.log(activeFilters)
})
const uniqueSelectorsOfFilters = {
easyList: ['[lazy-ad="leftthin_banner"]', '#ad_300x250_2'],
fanboyAnnoyances: ['#feedback-tab', '#taboola-below-article']
}
async function getActiveFilters(uniqueSelectors) {
// Collect all the selectors into a plain array
const allSelectors = [].concat(
...Object.values(uniqueSelectors)
)
const blockedSelectors = new Set(
await getBlockedSelectors(allSelectors)
)
return Object.keys(uniqueSelectors)
.filter(filterName => {
const selectors = uniqueSelectors[filterName]
let blockedSelectorCount = 0
for (const selector of selectors) {
if (blockedSelectors.has(selector)) {
++blockedSelectorCount
}
}
return blockedSelectorCount > selectors.length * 0.5
})
}
getActiveFilters(uniqueSelectorsOfFilters)
.then(activeFilters => {
console.log(activeFilters)
})
// See the snippet above
getBlockedSelectors(...)
.then(blockedSelectors => {
// See the murmurHash3 implementation at
// https://github.com/karanlyons/murmurHash3.js
const fingerprint = murmurHash3.x86.hash128(
JSON.stringify(blockedSelectors)
)
console.log(fingerprint)
})
// See the snippet above
getActiveFilters(...).then(activeFilters => {
// See the murmurHash3 implementation at
// https://github.com/karanlyons/murmurHash3.js
const fingerprint = murmurHash3.x86.hash128(
JSON.stringify(activeFilters)
)
console.log(fingerprint)
})
MacBook Pro 2015 (Core i7), macOS 11, Safari 14 | iPhone SE1, iOS 13, Safari 13 | Pixel 2, Android 9, Chrome 89 | |
---|---|---|---|
1 selector per filter (45 in total) | 3.1ms | 10ms | 5.7ms |
At most 5 selectors per filter (210 in total) | 9ms | 27ms | 17ms |
At most 10 selectors per filter (401 in total | 20ms | 20ms | 36ms |
All selectors (23029 in total) | ≈7000ms | ≈19000ms | ≈2600ms |