Addon using pageMod loads content script xpath.js to an open page:

//addon side mod = PageMod({ include: ['*'], contentScriptFile: data.url("./addonside/contentScript.js"), onAttach: function(worker) { worker.on('message', function(message) { console.log('mouseclick: ' + message); }); } }); 

The script defines global variables that are used to change the attributes of DOM elements:

 //content script var oldAttribute; var previousElem = null; var previousElemAttr = null; var allElems = []; // будет использован для подсветки дочерних элементов 

Event handlers are defined, within which the attributes of the DOM elements change:

 //content script window.addEventListener('click', clickListener, true); //"true" kill button click window.addEventListener('mouseover', mouseoverListener, true); window.addEventListener('mouseout', mouseoutListener, true); 

Inside handler functions, global variables are always available .

From the addon to the content script can be sent a message:

 //addon side mod.port.emit("alert", messageFromAddon); 

But global variables are NOT available for the handler of this message:

 //content script self.port.on('alert', function(messageFromAddon){ ..... previousElem.setAttribute('style', previousElemAttr); // восстанавливаем исходные атрибуты кликнутому элементу .... }); 

When processing an event, the following error occurs:

 console.error: JPM [error] Message: TypeError: previousElem is null 

The biggest oddity is that this is not always the case! Such a sequence of actions eliminates the error:

  1. running firefox with jpm run -b /usr/bin/firefox
  2. loading content script with pageMod
  3. Entering the URL into the browser's address bar and opening the page

In this case, the previousElem no longer be null , and working with it is always normal , I can access the attributes of the DOM element.

I want to understand what is happening and how to fix it?

log:

 console.error: JPM [error] Message: TypeError: previousElem is null Stack: @resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://firetemplate/data/addonside/xpath.js:5:2 onEvent@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://gre/modules/commonjs/sdk/content/content-worker.js:45:22 onEvent@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://gre/modules/commonjs/sdk/content/content-worker.js:45:22 onChromeEvent@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://gre/modules/commonjs/sdk/content/content-worker.js:91:16 

EDIT A simple example to play a bug: AddonForSO

  • The first. You yourself specify a global variable as null: var previousElem = null; . The second. Describe the sequence of actions when changing the code in the supplement. Those. how do you run it in the browser normally. And third, in the console of the browser Ctrl+J are there any other errors related to this add-on? - edem
  • Yes, previousElem was initially initialized as null, but later in the clickListener function, it is assigned a different value: var elem = event.target; previousElem = elem; var elem = event.target; previousElem = elem; And between two different clicks, the previousElem variable contains the old dom element - Alexander
  • The addon performs mod.port.emit("alert", messageFromAddon); only after the content script was loaded and only after some dom element was selected with a mouse click and the previousElem variable was initialized. Between different clicks (and different launches of handling the click event in the clickListener function), the value of the previousElem variable is preserved - Alexander
  • The principle of addition to me is clear. Answer two questions: 1) how do you develop an add-on, for example, change the code -> close the browser -> start the browser -> start the add-on or something else? 2) Are there any more errors for this addition in the Browser Console? - edem 2:41 pm
  • It seems that window.addEventListener and self.port.on work with different contexts - Alexander

1 answer 1

 var tabs = require("sdk/tabs"); tabs.activeTab.reload(); mod = pageMod.PageMod({...}); 

Before downloading the script, I update the page. Not the most elegant, but working way.

EDIT: Accidentally managed to understand the reasons for this behavior.

The fact is that include: ['*'] connects the script to all pages. Even the one in dev / panel . A situation arises where two listeners handle the same alert event. include: [getCurrentURL()] fixes this problem.