<commit_before>/**
 * @param {Object} a
 * @param {Object} b
 * @return {Object}
 */
function objectDiff(a, b) {

	if (a === b) {
		return {
			changed: 'equal',
			value: a
		}
	}

	var diff = {};

    //TODO: handle circular references

	for (var key in a) {
		if (key in b) {
			if (a[key] === b[key]) {
				diff[key] = {
					changed: 'equals',
					value: a[key]
				}
			} else {
				var typeA = typeof a[key];
				var typeB = typeof b[key];
				if ((typeA == 'object' || typeA == 'function') && (typeB == 'object' || typeB == 'function')) {
					diff[key] = {
						changed: 'object change',
						diff: objectDiff(a[key], b[key])
					}
				} else {
					diff[key] = {
						changed: 'primitive change',
						removed: a[key],<commit_msg>Handle circular references is not a job of objectDiff.<commit_after>/**
 * @param {Object} a
 * @param {Object} b
 * @return {Object}
 */
function objectDiff(a, b) {

	if (a === b) {
		return {
			changed: 'equal',
			value: a
		}
	}

	var diff = {};

	for (var key in a) {
		if (key in b) {
			if (a[key] === b[key]) {
				diff[key] = {
					changed: 'equals',
					value: a[key]
				}
			} else {
				var typeA = typeof a[key];
				var typeB = typeof b[key];
				if ((typeA == 'object' || typeA == 'function') && (typeB == 'object' || typeB == 'function')) {
					diff[key] = {
						changed: 'object change',
						diff: objectDiff(a[key], b[key])
					}
				} else {
					diff[key] = {
						changed: 'primitive change',
						removed: a[key],
{'fraction_non_alphanumeric': 0.19022103148024114, 'fraction_numerical': 0.0, 'mean_word_length': 2.357303370786517, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7097711', 'n_tokens_mistral': 692, 'n_tokens_neox': 548, 'n_words': 153}