Skip to content

Commit

Permalink
Support of multiple arguments for SC.hashFor. Fixes a bug caused by S…
Browse files Browse the repository at this point in the history
…C.Event#add overwriting previously registered event handlers.
  • Loading branch information
martoche committed Aug 28, 2010
1 parent 3bb2d15 commit 9ab45c5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 12 deletions.
4 changes: 2 additions & 2 deletions frameworks/foundation/system/event.js
Expand Up @@ -235,7 +235,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
}

// Build the handler array and add to queue
handlers[SC.guidFor(method)] = [target, method, context];
handlers[SC.hashFor(target, method)] = [target, method, context];
SC.Event._global[eventType] = YES ; // optimization for global triggers

// Nullify elem to prevent memory leaks in IE
Expand Down Expand Up @@ -313,7 +313,7 @@ SC.mixin(SC.Event, /** @scope SC.Event */ {
method = target[method] ;
}

delete handlers[SC.guidFor(method)] ;
delete handlers[SC.hashFor(target, method)];

// check to see if there are handlers left on this event/eventType.
// if not, then cleanup the handlers.
Expand Down
31 changes: 21 additions & 10 deletions frameworks/runtime/core.js
Expand Up @@ -388,26 +388,37 @@ SC.mixin(/** @scope SC */ {
},

/**
Returns a unique hash code for the object. If the object implements
a hash() method, the value of that method will be returned. Otherwise,
this will return the same value as guidFor().
Returns a unique hash code for the object. If the object implements
a hash() method, the value of that method will be returned. Otherwise,
this will return the same value as guidFor().
If you pass multiple arguments, hashFor returns a string obtained by
concatenating the hash code of each argument.
Unlike guidFor(), this method allows you to implement logic in your
code to cause two separate instances of the same object to be treated as
if they were equal for comparisons and other functions.
IMPORTANT: If you implement a hash() method, it MUST NOT return a
number or a string that contains only a number. Typically hash codes
IMPORTANT: If you implement a hash() method, it MUST NOT return a
number or a string that contains only a number. Typically hash codes
are strings that begin with a "%".
@param obj {Object} the object
@param obj {Object} the object(s)
@returns {String} the hash code for this instance.
*/
hashFor: function(obj) {
var hashFunc;
return (obj && (hashFunc = obj.hash) && (typeof hashFunc === SC.T_FUNCTION)) ? hashFunc.call(obj) : this.guidFor(obj) ;
},
hashFor: function() {
var len = arguments.length,
h = '',
obj, f, i;

for (i = 0; i < len; ++i) {
obj = arguments[i];
h += (obj && (f = obj.hash) && (typeof f === SC.T_FUNCTION)) ? f.call(obj) : this.guidFor(obj);
}

return h === '' ? null : h;
},

/**
This will compare the two object values using their hash codes.
Expand Down
33 changes: 33 additions & 0 deletions frameworks/runtime/tests/core/guidFor.js
Expand Up @@ -147,3 +147,36 @@ test("two instances with different value should have different guid", function()
test("guid should not parse to a number", function() {
equals(YES, isNaN(parseInt(SC.guidFor(array1), 0))) ;
});

var obj1, obj2, str, arr;

module("SC.hashFor", {
setup: function() {
obj1 = {};
obj2 = {
hash: function() {
return '%1234';
}
};
str = "foo";
arr = ['foo', 'bar'];
}
});

test("One argument", function() {
equals(SC.guidFor(obj1), SC.hashFor(obj1), "guidFor and hashFor should be equal for an obj1ect");
equals(obj2.hash(), SC.hashFor(obj2), "hashFor should call the hash() function if present");
equals(SC.guidFor(str), SC.hashFor(str), "guidFor and hashFor should be equal for a string");
equals(SC.guidFor(arr), SC.hashFor(arr), "guidFor and hashFor should be equal for an array");
});

test("Multiple arguments", function() {
var h = [
SC.guidFor(obj1),
obj2.hash(),
SC.guidFor(str),
SC.guidFor(str)
].join('');

equals(h, SC.hashFor(obj1, obj2, str, arr), "hashFor should concatenate the arguments' hashes when there are more than one");
});

0 comments on commit 9ab45c5

Please sign in to comment.