//diff.js
/*global adventurejs A*/
"use strict";
/**
* 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 diff_object = {};
var starttime = new Date().getTime();
for (var prop in updated_object)
{
//if( false === updated_object.hasOwnProperty(prop) ) continue;
if( false === Object.prototype.hasOwnProperty.call(updated_object, prop) ) continue;
// if prop is of different type, include in diff
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
if( "undefined" === typeof baseline_object[prop] )
{
diff_object[ prop ] = A.clone( updated_object[ prop ] );
continue;
}
// Handle the 3 simple types, and null or undefined
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;
}
// Handle Array - just stringify, it's not worth worrying about
// the complexity of splicing or reordering
if ( updated_object[ prop ] instanceof Array )
{
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
if ( updated_object[ prop ] instanceof 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
if ( updated_object[ prop ] instanceof 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;
}