Someone to check & test my code, Toolbox bug suspiction

I have found strange behaviour of Content Toolbox tool. I have no explanation for this behaviour, so I look for somebody who can test it and possibly find a bug.

Using FF version 48.0b10, jquery min injected to Content Scripts. Another content script is named inspector.js

I add my addon to addon Debugger and then I open mozilla page as an example page.

Then I press ctrl+alt+shift+I to run Browser Content, I search for inspector.js.

First I add breakpoint on line 32 to test the for loop, then I add breakpoint on line 39 to test if the div will appear near the area where I clicked.

The inspector.js (all rights reserved by h4ever) follows:

document.body.style.border = "80px solid green";

var maxLevel = 20;
var elements = { length: 0, collection:[] };

// // Handle messages from the add-on background page:
chrome.runtime.onMessage.addListener(
  function (package){
    if (package.command !== "inspector")
      return false;
    console.log("Recieved message:");
    
    document.addEventListener('click', function(e)
    {  
    getParent(e.target);
    var node1 = $("#test_styles");
    var node2 = $("#test_panel");
    if ( node1.length ) node1.remove();
    if ( node2.length ) node2.remove();

    var ClientW = jQuery(window).width();
    var ClientH = jQuery(window).height();  
    var y = (e.clientY < ClientH / 6 )?e.clientY+80:
         (e.clientY > ClientH - ClientH / 6 )?e.clientY-80:e.clientY;
    var x = (e.clientX < ClientW / 4 )?e.clientX+80:
         (e.clientX > ClientW - ClientW / 4 )?e.clientX-80:e.clientX;  	    

    $("html > head").append("<style id=test_styles>div#test_panel { position: absolute; border-radius: 3px; font-family:'Arial Black'; font-size:13px; }</style>\n\r");      
    $("body").append("<div id=test_panel></div>");
    $('div#test_panel').append("<ul>");
    var level = elements.length;
    for (var level = elements.length; 
        level>1 ; 
        level--)
      {
      $('div#test_panel ul').append("<li>" + elements.collection[level].tag + "</li>\r\n");
      }    
    });
    $('#test_panel').css({ left: x, top: y })  
  
  }
  );

function getParent(element, level = 0 ){  

  level++;
  elements.collection[level] = { tag: "", attrs: {} }
  elements.collection[level].tag = element.nodeName; 
  
  console.log(element.parentElement);
  
  attrs = element.attributes;  
  elements.collection[level].attrs = { vals: [] , names: [] };
  for (var i = 0; i < attrs.length; i++)
    {
      elements.collection[level].attrs.names.push(attrs[i].name);
      elements.collection[level].attrs.vals.push(attrs[i].value);
    } 
  
  if (null === element.parentElement || level > maxLevel)
    {
    elements.length = level;
    return false;
    }
  else
    getParent(element.parentElement, level);
  
  return true;  
}

The results:

  1. Test of for loop.
    The for loop is performed and finished, but this is reapeated 3 times which is not normal. Why?
  2. Test of the line 39. The variables x, y and level are not accessible in this context. Why? Therefor the function .css fails.

Can you explain this behaviour?
Is the bug on my site or is it Firefox - Toolbox problem?

I took the freedom to run your code through a JS beautifier to fix the seemingly random indents:

document.body.style.border = "80px solid green";

var maxLevel = 20;
var elements = {
    length: 0,
    collection: []
};

// // Handle messages from the add-on background page:
chrome.runtime.onMessage.addListener(
    function(package) {
        if (package.command !== "inspector")
            return false;
        console.log("Recieved message:");

        document.addEventListener('click', function(e) {
            getParent(e.target);
            var node1 = $("#test_styles");
            var node2 = $("#test_panel");
            if (node1.length) node1.remove();
            if (node2.length) node2.remove();

            var ClientW = jQuery(window).width();
            var ClientH = jQuery(window).height();
            var y = (e.clientY < ClientH / 6) ? e.clientY + 80 :
                (e.clientY > ClientH - ClientH / 6) ? e.clientY - 80 : e.clientY;
            var x = (e.clientX < ClientW / 4) ? e.clientX + 80 :
                (e.clientX > ClientW - ClientW / 4) ? e.clientX - 80 : e.clientX;

            $("html > head").append("<style id=test_styles>div#test_panel { position: absolute; border-radius: 3px; font-family:'Arial Black'; font-size:13px; }</style>\n\r");
            $("body").append("<div id=test_panel></div>");
            $('div#test_panel').append("<ul>");
            var level = elements.length;
            for (var level = elements.length; level > 1; level--) {
                $('div#test_panel ul').append("<li>" + elements.collection[level].tag + "</li>\r\n");
            }
        });
        $('#test_panel').css({
            left: x,
            top: y
        })

    }
);

function getParent(element, level = 0) {

    level++;
    elements.collection[level] = {
        tag: "",
        attrs: {}
    }
    elements.collection[level].tag = element.nodeName;

    console.log(element.parentElement);

    attrs = element.attributes;
    elements.collection[level].attrs = {
        vals: [],
        names: []
    };
    for (var i = 0; i < attrs.length; i++) {
        elements.collection[level].attrs.names.push(attrs[i].name);
        elements.collection[level].attrs.vals.push(attrs[i].value);
    }

    if (null === element.parentElement || level > maxLevel) {
        elements.length = level;
        return false;
    } else
        getParent(element.parentElement, level);

    return true;
}

First to why x and y are not defined: the $.css is run after the listener was added, and not at the end of the listener as should be quite clear from the version of the code I posted above.

Further you don’t have to set var level = elements.length; before the for loop, the initialization statement will do that.

Thank you. I thought it is some harder problem expecting days of delay. I know the declaration of level was redundant.

BTW: Did you noticed, you changed order of the listed items ?
(var i = 0; i < attrs.length; i++)
vs
(var level = elements.length; level>1 ; level–)

I had not noticed that, probably a setting within the transformer I used. I guess it’s to avoid reading .length every iteration step, as it can not know that this is a static property and not an actual array length property.

I do not understand your last reply. I have initiated the level to = elements.lenght so there is no change to be a length detected in every iteration.

Yes, but doing it this way saves even a variable. I’m not sure it’s worth it, it’s just an “optimization” the tool used seemed to have applied. There’s not much more to it.

True, the first part of the for command could be omitted completely.