//diff.js
/*global adventurejs A*/
/**
* diff function for comparing objects.
* Specifically intended to support UNDO and SAVE / RESTORE.
* It recurses objects, stringifies arrays, copies others.
* @method adventurejs.Game#diff
* @memberOf adventurejs.Game
* @param {Object} baseline_object Old object
* @param {Object} updated_object New object
* @returns {Object}
*/
adventurejs.diff = function Adventurejs_diff(baseline_object, updated_object) {
var starttime = new Date().getTime();
var diff_object = {};
for (var prop in updated_object) {
if (false === Object.prototype.hasOwnProperty.call(updated_object, prop)) {
continue;
}
// if prop is of different type, include in diff
else if (typeof updated_object[prop] !== typeof baseline_object[prop]) {
diff_object[prop] = A.clone(updated_object[prop]);
continue;
}
// if updated_object prop doesn't exist in baseline_object, include in diff
else if (
"undefined" === typeof baseline_object[prop] &&
"undefined" !== typeof updated_object[prop]
) {
diff_object[prop] = A.clone(updated_object[prop]);
continue;
}
// Handle the 3 simple types, and null or undefined
else if (
(null == updated_object[prop] ||
"object" != typeof updated_object[prop]) &&
updated_object[prop] !== baseline_object[prop]
) {
diff_object[prop] = A.clone(updated_object[prop]);
continue;
}
// else if (Array.isArray(updated_object[prop])) {
// var baseline_object_prop = JSON.stringify(baseline_object[prop]);
// var updated_object_prop = JSON.stringify(updated_object[prop]);
// if (updated_object_prop !== baseline_object_prop) {
// console.warn("BAZINGA!!!");
// console.log("prop", prop);
// console.log("baseline_object_prop", baseline_object_prop);
// console.log("updated_object_prop", updated_object_prop);
// diff_object[prop] = JSON.parse(updated_object_prop);
// }
// continue;
// }
// Handle Array - just stringify, it's not worth worrying about
// the complexity of splicing or reordering
else if (Array.isArray(updated_object[prop])) {
var baseline_object_prop = JSON.stringify(baseline_object[prop]);
var updated_object_prop = JSON.stringify(updated_object[prop]);
if (updated_object_prop !== baseline_object_prop) {
diff_object[prop] = JSON.parse(updated_object_prop);
}
continue;
}
// Handle Object - recursive
else if (typeof updated_object[prop] === "function") {
// this version does stringify then parse - unsure its necessary
// var baseline_object_prop = JSON.stringify( baseline_object[ prop ],
// function(key, val) {
// return val.toString()
// });
// var updated_object_prop = JSON.stringify( updated_object[ prop ],
// function(key, val) {
// return val.toString()
// });
// this version converts to string without stringify
var baseline_object_prop = baseline_object[prop].toString();
var updated_object_prop = updated_object[prop].toString();
if (updated_object_prop !== baseline_object_prop) {
diff_object[prop] = eval("(" + updated_object_prop + ")");
}
continue;
}
// Handle Object - recursive
else if (typeof updated_object[prop] === "object") {
var diff_object_prop = A.diff(
baseline_object[prop],
updated_object[prop]
);
var diff_object_prop_keys = Object.keys(diff_object_prop);
if (0 < diff_object_prop_keys.length) {
diff_object[prop] = diff_object_prop;
}
continue;
}
}
return diff_object;
};