Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hasOwnProperty() not working in Chrome for array

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:

enter image description here

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:

enter image description here

like image 288
Pete Avatar asked Dec 12 '16 15:12

Pete


1 Answers

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

like image 151
Pete Avatar answered Sep 17 '22 19:09

Pete