Максимальный размер стека вызовов превышен, когда я изменяю слова на веб-странице через скрипт содержимого расширения Chrome - PullRequest
0 голосов
/ 12 июня 2019

Я создаю расширение Chrome, которое ищет слово, и если это слово присутствует на веб-странице, оно размыто. Чтобы добиться этого, я ищу все текстовые узлы (тип узла 1) на веб-странице и заменяю их новым узлом. Проблема возникает, когда я создаю новый узел и присваиваю ему текст заменяемого узла, этот скрипт при запуске выдает ошибку «RangeError: Превышен максимальный размер стека вызовов»

Эта проблема не возникает, когда я назначаю постоянную строку для создаваемого узла. И этот скрипт работает нормально.

var targetNode=document.body    
var config = { attributes: true, childList: true, subtree: true };
var callback = function(mutationsList, observer) {
walk(document.body);
};


var observer = new MutationObserver(callback);
observer.observe(targetNode, config);

function walk(node) 
{
var child, next;

switch ( node.nodeType )  
{
    case 1:  // Element
    case 9:  // Document
    case 11: // Document fragment
        child = node.firstChild;
        while ( child ) 
        {
            next = child.nextSibling;
            walk(child);
            child = next;
        }
        break;

    case 3: // Text node
        handleText(node);
        break;
}
}

function handleText(textNode) 
{

var str = textNode.nodeValue;
if (str == "Manchester"){
//console.log(str);

p=textNode.parentNode;
const modified = document.createElement('span');
modified.id="bblur";
modified.textContent = "Constant";     // this works
modified.style.filter="blur(5px)";
modified.addEventListener("mouseover", mouseOver, false);
modified.addEventListener("mouseout", mouseOut, false);
p.replaceChild(modified, textNode);
}

//textNode.nodeValue = str;

//textNode.style.filter="blur(5px)";

}


function mouseOver()
{  
this.style.filter="blur(0px)";
}

function mouseOut()
{  
this.style.filter="blur(5px)";
}

Эта функция handleText не работает

function handleText(textNode) 
{

var str = textNode.nodeValue;
if (str == "Manchester"){
//console.log(str);

p=textNode.parentNode;
const modified = document.createElement('span');
modified.id="bblur";
modified.textContent = str;   //this doesn't work :/
modified.style.filter="blur(5px)";
    modified.addEventListener("mouseover", mouseOver, false);
    modified.addEventListener("mouseout", mouseOut, false);
p.replaceChild(modified, textNode);
}


}

Я не хочу, чтобы новый узел создавался с фиксированной строкой, но я хочу текстовое содержимое старого узла в новом. Что я могу сделать, чтобы избежать этой проблемы с пределом стека вызовов. Спасибо!

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Как уже упоминалось, бесконечный цикл - это модификация DOM, которая запускает обратный вызов, который модифицирует DOM и т. Д.

Возможно, сначала запустите код.Зарегистрируйте слушателя, когда слушатель сработает, удалите слушателя.После внесения изменений зарегистрируйте прослушиватель еще раз.

Таким образом, ваш код не будет срабатывать сам по себе и будет прослушивать изменения только в режиме ожидания.

Думайте о нем как о удерживающей странице насайт электронной коммерции.Если вы перемещаете базу данных, но все еще принимаете заказы, это станет грязным.Таким образом, вы отключаете прием новых заказов, пока выполняете обработку, и включаете их, как только закончите.Та же логика здесь

0 голосов
/ 12 июня 2019

Бесконечный цикл вызван тем, что вы модифицируете DOM из обратного вызова MutationObserver. Он работает с "Constant", потому что у вас есть условие "if (str == "Manchester")", которое запрещает модификацию DOM и не вызывает обратный вызов MutationObserver. Попробуйте использовать константу "Manchester", и вы снова увидите бесконечный цикл. Самое простое решение - игнорировать узлы, которые вы уже заменили:

function walk(node) 
{
  var child, next;

  switch ( node.nodeType )  
  {
      case 1:  // Element
      case 9:  // Document
      case 11: // Document fragment
          child = node.firstChild;
          while ( child ) 
          {
              next = child.nextSibling;
              if (child.id !== 'bblur') {
                  walk(child);
              }
              child = next;
          }
          break;

      case 3: // Text node
          handleText(node);
          break;
  }
}

Также ваш код будет назначать один и тот же идентификатор всем замененным элементам. Было бы лучше использовать другой способ пометки новых узлов, например, вы можете использовать dataset атрибуты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...