Skip to content

Instantly share code, notes, and snippets.

@dubzzz
Last active December 15, 2020 08:34
Show Gist options
  • Save dubzzz/507939a2ade310c0e4ed8dee56e4aa1b to your computer and use it in GitHub Desktop.
Save dubzzz/507939a2ade310c0e4ed8dee56e4aa1b to your computer and use it in GitHub Desktop.
// Log everything
function logAllCalls(ClassType) {
for (const k in ClassType.prototype) {
try {
if (typeof ClassType.prototype[k] !== "function") {
continue;
}
}
catch(err) {
continue;
}
const sourceMethod = ClassType.prototype[k];
ClassType.prototype[k] = function(...args) {
console.log(k, ...args);
return sourceMethod.apply(this, args);
}
}
}
logAllCalls(HTMLElement);
// Only focus on some operations
const __createElement__lastValues = new Map();
const __createElement = document.createElement;
document.createElement = function(...args) {
const el = __createElement.apply(this, args);
el.addEventListener("DOMCharacterDataModified", function(event) {
const hierarchyTags = [];
for (let node = event.target ; node != null ; node = node.parentNode) {
hierarchyTags.push(node.tagName);
}
if (hierarchyTags.includes('STYLE')) {
// Ignore <style/> updates
return;
}
if (!__createElement__lastValues.has(event.target)) {
__createElement__lastValues.set(event.target, Object.create(null));
}
const lastValues = __createElement__lastValues.get(event.target);
if (lastValues[event.attrName] !== event.newValue) {
lastValues[event.attrName] = event.newValue;
console.log('Updating ', event.target, ' on ', event.attrName, ' from ', event.prevValue, ' to ', event.newValue, ' resulting in ', event.target.wholeText);
}
}, false);
return el;
}
const __appendChild = HTMLElement.prototype.appendChild;
HTMLElement.prototype.appendChild = function(...args) {
const out = __appendChild.apply(this, args);
if (this.parentNode) {
console.log('Appending ', args[0], ' to ', this);
}
return out;
}
const __removeChild = HTMLElement.prototype.removeChild;
HTMLElement.prototype.removeChild = function(...args) {
console.log('Removing ', args[0], ' from ', this);
return __removeChild.apply(this, args);
}
// React createElement timings
const __REACT_DEBUG: any = React;
(window as any).__REACT_DEBUG = __REACT_DEBUG;
const __createElement = __REACT_DEBUG.createElement;
__REACT_DEBUG.createElement = function(...args: any) {
const fun = args[0];
// See https://overreacted.io/how-does-react-tell-a-class-from-a-function/
if (
typeof fun !== 'function' ||
fun instanceof __REACT_DEBUG.Component ||
fun.isReactClass ||
(fun.prototype && fun.prototype.isReactComponent)
) {
return __createElement.apply(this, args);
}
const timedRender = function(...args: any) {
const chronoInit = performance.now();
const out = fun(...args);
const chronoEnd = performance.now();
console.log(`${fun.name} rendered in ${chronoEnd - chronoInit}ms with props `, args[0]);
return out;
};
return __createElement.apply(this, [timedRender, ...args.slice(1)]);
};
@dubzzz
Copy link
Author

dubzzz commented Dec 15, 2020

// Log everything

function logAllCalls(ClassType) {
	for (const k in ClassType.prototype) {
		try {
			if (typeof ClassType.prototype[k] !== "function") {
				continue;
			}
		}
		catch(err) {
			continue;
		}
		const sourceMethod = ClassType.prototype[k];
		ClassType.prototype[k] = function(...args) {
			console.log(k, ...args);
			return sourceMethod.apply(this, args);
		}
	}
}

// Only focus on some operations

const __createElement__lastValues = new Map();
const __createElement = document.createElement;
document.createElement = function(...args) {
	const el = __createElement.apply(this, args);

	el.addEventListener("DOMCharacterDataModified", function(event) {
		const hierarchyTags = [];
		for (let node = event.target ; node != null ; node = node.parentNode) {
			hierarchyTags.push(node.tagName);
		}
		if (hierarchyTags.includes('STYLE')) {
			// Ignore <style/> updates
			return;
		}
		if (!__createElement__lastValues.has(event.target)) {
			__createElement__lastValues.set(event.target, Object.create(null));
		}
		const lastValues = __createElement__lastValues.get(event.target);
		if (lastValues[event.attrName] !== event.newValue) {
			lastValues[event.attrName] = event.newValue;
			console.log('Updating ', event.target, ' on ', event.attrName, ' from ', event.prevValue, ' to ', event.newValue, ' resulting in ', event.target.wholeText);
		}
	}, false);

	return el;
}
const __appendChild = HTMLElement.prototype.appendChild;
HTMLElement.prototype.appendChild = function(...args) {
	const out = __appendChild.apply(this, args);
	if (this.parentNode) {
		console.log('Appending ', args[0], ' to ', this);
	}
	return out;
}
const __removeChild = HTMLElement.prototype.removeChild;
HTMLElement.prototype.removeChild = function(...args) {
	console.log('Removing ', args[0], ' from ', this);
	return __removeChild.apply(this, args);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment