cbbf5abd7a
* test: test for DOM listener memory leaks * fix whitespace change, unintended
88 lines
2.3 KiB
JavaScript
88 lines
2.3 KiB
JavaScript
import { ClientFunction as exec } from 'testcafe'
|
|
|
|
export const installDomListenerListener = exec(() => {
|
|
function eql (a, b) {
|
|
const aType = typeof a
|
|
const bType = typeof b
|
|
switch (aType) {
|
|
case 'boolean':
|
|
return bType === 'boolean' && b === a
|
|
case 'undefined':
|
|
return bType === 'undefined'
|
|
case 'object':
|
|
if (a === null) {
|
|
return b === null
|
|
}
|
|
if (b === null) {
|
|
return false
|
|
}
|
|
if (Object.keys(a).length !== Object.keys(b).length) {
|
|
return false
|
|
}
|
|
for (const key of Object.keys(a)) {
|
|
if (a[key] !== b[key]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
function spyAddListener (proto) {
|
|
const addEventListener = proto.addEventListener
|
|
proto.addEventListener = function (type, listener, options) {
|
|
if (!this.__listeners) {
|
|
this.__listeners = {}
|
|
}
|
|
if (!this.__listeners[type]) {
|
|
this.__listeners[type] = []
|
|
}
|
|
this.__listeners[type].push({ listener, options })
|
|
return addEventListener.apply(this, arguments)
|
|
}
|
|
}
|
|
|
|
function spyRemoveListener (proto) {
|
|
const removeEventListener = proto.removeEventListener
|
|
proto.removeEventListener = function (type, listener, options) {
|
|
if (this.__listeners && this.__listeners[type]) {
|
|
const arr = this.__listeners[type]
|
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
const { listener: otherListener, options: otherOptions } = arr[i]
|
|
if (listener === otherListener && eql(options, otherOptions)) {
|
|
arr.splice(i, 1)
|
|
}
|
|
}
|
|
}
|
|
return removeEventListener.apply(this, arguments)
|
|
}
|
|
}
|
|
|
|
function spy (proto) {
|
|
spyAddListener(proto)
|
|
spyRemoveListener(proto)
|
|
}
|
|
|
|
spy(Element.prototype)
|
|
spy(document)
|
|
spy(window)
|
|
})
|
|
|
|
export const getNumDomListeners = exec(() => {
|
|
function getNumListeners (obj) {
|
|
let sum = 0
|
|
if (obj.__listeners) {
|
|
for (const key of Object.keys(obj.__listeners)) {
|
|
sum += obj.__listeners[key].length
|
|
}
|
|
}
|
|
return sum
|
|
}
|
|
|
|
return [...document.querySelectorAll('*')]
|
|
.concat([window, document])
|
|
.map(getNumListeners)
|
|
.reduce((a, b) => a + b, 0)
|
|
})
|