0

I have encountered one of the most bizzare and frustrating behaviours yet. I have sample data:

var nodes = [ //Sample data
  {
    ID: 1,
    Chart: 1,
    x: 50,
    y: 50,
    width: 100,
    height: 80,
    color: "#167ee5",
    text: "Start",
    label: "Start",
    targets: [2]
  },
  {
    ID: 2,
    Chart: 1,
    x: 500,
    y: 170,
    width: 100,
    height: 80,
    color: "#167ee5",
    text: "End",
    label: "End",
    targets: [3]
  },
  {
    ID: 3,
    Chart: 1,
    x: 270,
    y: 350,
    width: 100,
    height: 80,
    color: "#167ee5",
    text: "Mid",
    label: "Mid",
    targets: []
  }
];

for my web application. The issue is with the targets attribute. As you can see it is array. However when I do

console.log(nodes[0]);

and inspect the result in the browser it shows that the value for targets at index 0 is undefined. Same for every other targets that has some values in them (whether 1 or more).

However if I do

console.log(nodes.[0].targets);

it prints out [2]. If I do Array.isArray(nodes[0].targets) it returns false, yet if I do console.log(nodes[0]) and inspect the result in the browser console, it shows that the object prototype is in fact Array and simply the value at index 0 is undefined.

It worked the day before and now it doesn't. The only thing I did was I restructured the object that uses this variable later. But the console log is being called before the object is even instantiated for the first time (and it doesn't change the nodes var anyway, only reads it).

Does anyone have any clues as to what might be causing this behaviour. If it helps I am using Paperscript and this code runs in the paperscript scope (as it did before when everything worked fine).

UPDATE

Ok after more blind debugging I have determined the block of code that causes the issue, how or why is completely beyond me.

Basically I define an object constructor beflow. The constructor loops through the nodes, makes Paperscript shapes and adds the targets to the arbitrary data attribute of the paperJS path object:

function Flowchart(nodes, chartdata) {
  //Member vars. They are only used internally
  var connections = [];
  var shapes = [];
  var connectors = [];

  //Constructor operations
  createShapes(nodes); //If I uncomment this, the problem goes away

  //...
  function createShapes(nodes) {
    nodes.forEach(function (node) { //for each node data entry
      console.log(node); //At this point, the targets are screwed up already
      var point = new Point(node.x, node.y); //make a PaperJS point for placement
      var size = new Size(node.width, node.height); //make a PaperJS size object
      var shape = makeRectangle(point, size, 8, node.color); //Pass to the object instantiating function
      shape.data = { //Store arbitrary data for programming reference.
        ID: node.ID,
        label: node.label,
        text: node.text,
        'connectors': {
          to: [],
          from: []
        },
        targets: node.targets //this is undefined
      };
      console.log(node.targets) //this logs [2] or [3] but not Array[1]...
      shapes.push(shape); //Store reference for later
    });
    shapes.forEach(function (shape) { //loop though all drawn objects
      if (shape.data.targets.length > 0) { //if shape has targets
        var targets = _.filter(this.shapes, function (target) {
          return _.contains(shape.data.targets, target.data.ID);
        });
        for (var i = 0; i < shape.data.targets.length; i++) {
          shape.data.targets[i] = targets[i]; //Replace the ID-type reference with drawn object reference
        }
      }
     });
    }
     //... The rest of the object
    }
    console.log(nodes); 
    //It doesnt seem to matter whether i put this before or after instantiating. 
    //It doesnt even matter IF I instantiate in the first place.
    var chart = new Flowchart(nodes, chartdata);
Community
  • 1
  • 1
Megakoresh
  • 746
  • 1
  • 11
  • 30
  • What other code do you have? See http://stackoverflow.com/q/4057440/1048572 – Bergi Feb 23 '15 at 11:22
  • Ok after more blind debugging I have determined the block of code that causes the issue, how or why is completely beyond me. I will add it to the question. – Megakoresh Feb 23 '15 at 11:41
  • Yes please, [edit] it in! – Bergi Feb 23 '15 at 11:53
  • Ok I have tried to minimize the object code down to the part that causes the problem to the best of my ability (it's a complex structure). – Megakoresh Feb 23 '15 at 12:13
  • I would say that the line `shape.data.targets[i] = targets[i]` is screwing up your arrays. Your logged values [are rather meaningless](http://stackoverflow.com/a/23392650/1048572) – Bergi Feb 23 '15 at 12:37
  • It seems the issue was in using a forEach loop instead of a standard `for(var i...)`. However I looped though this array before using forEach and there were no problems whatsoever. All I changed was convert the Flowchart from a var into a constructor function (with the corresponding syntax changing). I would still welcome an explanation as to what causes this behaviour. – Megakoresh Feb 23 '15 at 12:38

1 Answers1

0

This behaviour has been caused by the changes to how Chrome treats enumerable properties of objects. Because Chrome updates silently, it's impossible to notice.

It must have been causing me a lot of headache if I remembered the cause after all this time... (Also it's embarrassing how bad I was at writing questions, but I guess that I realise it means I have progressed since then somewhat).

Megakoresh
  • 746
  • 1
  • 11
  • 30