Pre-release
Adventure.js Docs Downloads
Score: 0 Moves: 0
//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;
}