James Baker
James Baker

Reputation: 1256

Firefox Extension is Preventing Javascript Running

I'm writing a simple Firefox web extension, which will replace certain words (e.g. acronyms) with expanded versions. My code is as follows:

var replacements = [];
replacements["example1"] = "My First Example";
replacements["example2"] = "Second Example";

if(!window.location.href.startsWith('https://ignore.thissite.com/')){
    for(key in replacements){
        replaceOnDocument(new RegExp('\\b'+key+'\\b', 'gi'), '{{{REPLACE_'+key+'}}}');
        document.body.innerHTML = document.body.innerHTML.replace(new RegExp('{{{REPLACE_'+key+'}}}', 'g'), '<abbr title="'+key+'">'+replacements[key]+'</abbr>');
    }
}

function replaceOnDocument(pattern, string){
    Array.from(document.querySelectorAll("body, body *:not(script):not(noscript):not(style):not(code):not(pre)"))
        .forEach(someNode => Array.from(someNode.childNodes)
        .filter(childNode => childNode.nodeType == 3)
        .forEach(textNode => textNode.textContent = textNode.textContent.replace(pattern, string)));
}

This seems to replace all the instances as expected, but I've noticed that Javascript doesn't seem to run correctly on pages that the script has run on. I've been staring at the code for half an hour now and can't work out why that would be the case. To make things worse, the problem seems to be intermittent (although happens more often than not).

Any ideas as to why my code would prevent Javascript running as expected?

Upvotes: 0

Views: 61

Answers (1)

Robbendebiene
Robbendebiene

Reputation: 4859

I already speculated that replacing the content of body.innerHTML may cause issues, so how about using the following approach for replacing text? codepen example

const walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_TEXT,
  {
    // filter / exclude tags
    acceptNode: function (node) {
      return node.parentElement.nodeName === "SCRIPT" ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT;
    }
  }
);

while (walker.nextNode()) {
  // replace every H with @
  walker.currentNode.nodeValue = walker.currentNode.nodeValue.replace("H", "@");
}

This iterates over every text node excluding script text nodes and replaces their content.

Upvotes: 1

Related Questions