I've inherited some Javascript code and I'm not really a Javascript expert.
We have an object that acts like a collection of hashes and values called buckets
. It has properties that are the hash value and each property is an object. Here's what it looks like in the browser's debugger:
We have a containsKey()
function that uses hasOwnProperty()
to check for the existence of a hash in the buckets object.
containsKey: function(key) {
var hash = this.comparer.getObjectHashCode(key);
if (!this.buckets.hasOwnProperty(hash))
return false;
var array = this.buckets[hash];
for (var i = 0; i < array.length; i++) {
if (this.comparer.areEqual(array[i].key, key))
return true;
}
return false;
}
This code has worked flawlessly for at least 3 years. In the past week or two it stopped working in Chrome. Still works fine in IE (not sure about FF).
It seems to me that it ought to continue to work. I've validated that buckets
contains the hash property being searched. But the hasOwnProperty()
is now returning false.
Is there a more appropriate function I should use here?
Here's where it's failing in the debugger:
There appears to be some sort of bug in Chrome that was introduced when we upgraded from Chrome version 54.0.2840.99 to 55.0.2883.75 on Dec. 2, 2016.
The solution to our particular issue was to change our hash function to only return positive numbers. While small tests using negative numbers appears to work fine (as per squint's example in the comments), in our application they no longer work in Chrome.
I don't have a lot of time to dig into it. I don't know if it has to do with the number of items (we only have about 170 or so items in our "bucket").
Update:
gre_gor, in a comment above produced a sample that demonstrates the bug:
obj = {
buckets: {},
comparer: {
getObjectHashCode: function(str) { // hardcoded magic hashing
return {
"SUPPLYINVENTORY/SUPTRANSENTRY": -1525029354,
"PROPANE/LOADPROPANETOGROWERAR": 115289505
}[str.toUpperCase()];
},
areEqual: function(a, b) {
return a.toUpperCase() == b.toUpperCase();
}
},
containsKey: function(key) {
var hash = this.comparer.getObjectHashCode(key);
if (!this.buckets.hasOwnProperty(hash))
return false;
var array = this.buckets[hash];
for (var i = 0; i < array.length; i++) {
if (this.comparer.areEqual(array[i].key, key))
return true;
}
return false;
}
};
obj.buckets[-1525029354] = [{
key: "SUPPLYINVENTORY/SUPTRANSENTRY",
value: "$SupTransEntry object"
}];
obj.buckets[115289505] = [{
key: "PROPANE/LOADPROPANETOGROWERAR",
value: "$LoadPropaneToGrowerAR object"
}];
console.log(obj.containsKey("SUPPLYINVENTORY/SUPTRANSENTRY"), obj.containsKey("PROPANE/LOADPROPANETOGROWERAR"));
The text "true true" should go to the console, but in Chrome 55, it produces "false true".
Thank you gre_gor for a test that reliably reproduces the issue. I've reported the bug to Google.
Update #2: A bug was submitted 3 days before my submission for it. The issue has been fixed and will be out soon enough that I'm not going to have to work around it. -- Chromium Bug #673008
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With