Как отладить ScriptError в строке 0 в веб-просмотре? - PullRequest
1 голос
/ 25 сентября 2019

Я создал мобильное веб-приложение в формате html / js и использую «window.onerror» для отслеживания ошибок js на стороне клиента и сообщения о них на сервер.

Недавно я заметил, что получаю много отчетовScriptError on line 0.

Быстрый поиск в Google привел меня к таким дискуссиям, как Загадочная «Ошибка скрипта».сообщается в Javascript в Chrome и Firefox и https://ravikiranj.net/posts/2014/code/how-fix-cryptic-script-error-javascript/

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

После многих часов отладки я придумал следующий минимальный пример для воспроизведения ошибки:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Test</title>
  <meta name="google" content="notranslate"/>

  <script type="text/javascript">
  function init() {
    window.onerror = function() {
      alert(JSON.stringify(arguments));
    }
  }
  </script>
</head>
<body onload="init()">
  <h1>Hello</h1>
  <svg width="300" height="300">
    <a href="#">
      <rect x="50" y="50" width="200" height="200" />
    </a>
  </svg>
  <p>
  <a href="#">Link</a>
  </p>
</body>
</html>

Как мы видим, это простой HTMLстраница без JavaScript, за исключением самого обработчика ошибки.

В Safari (ios 12.4.1) ошибка не вызывается.Но как в Google Chrome для iOS, так и в Firefox для iOS сообщение ScriptError on line 0 сообщается каждый раз при нажатии на ссылку внутри элемента <svg> - но не при нажатии на ссылку за пределами <svg>.Обратите внимание, что к <svg>.

не подключен обработчик событий js. Живая версия кода доступна онлайн по адресу https://static.laszlokorte.de/scripterror.php

Я знаю, что все сторонние браузеры на iOS на самом деле просто используютСафари под капотом расширяется с несколькими пользовательскими функциями.Я подозреваю, что эти пользовательские функции вызывают ошибку, но я не знаю, как отследить ее дальше.

Почему щелчок по ссылке внутри простого элемента svg вызывает ошибку в iOS Chrome и Firefox, но не в Safari?Есть ли способ подключить инструменты Safari Webdev к мобильным браузерам, отличным от собственного Safari?

Обновление

После более глубокого изучения исходного кода Chrome (iOS) и Firefox (iOS)Теперь я нашел причину проблемы.Оба браузера вводят код JavaScript, который выполняется на touchstart и обрабатывает целевой узел события.Оба браузера проверяют, были ли затронуты элементы '' или '', и пытаются получить доступ к их атрибуту href или src соответственно.Затем они оба пытаются отправить значения атрибутов через webkit.postMessage хост-приложению.

Ошибка, по-видимому, вызвана тем фактом, что элемент <a> внутри <svg> на самом деле является SVGAElementи атрибут href - это не String, а SVGAnimatedString, который (кроме String) нельзя клонировать для отправки другому процессу.

Соответствующий код для Firefox можно найти здесь: https://github.com/mozilla-mobile/firefox-ios/blob/826cb396a9eb225b7eb667b47b245e2d98d26ed8/Client/Frontend/UserContent/UserScripts/AllFrames/AtDocumentEnd/ContextMenu.js#L14-L35

Код для Chrome находится здесь: https://github.com/chromium/chromium/blob/master/ios/web/web_state/js/resources/all_frames_context_menu.js#L136-L139

Так что для Chrome решение на самом деле простое, потому чтоэто позволяет явно отказаться от всего этого, установив свойство css -webkit-touch-callout: none (вы можете проверить это в связанном файле).Например, вот так:

@namespace svg url(http://www.w3.org/2000/svg);

svg|a {
  -webkit-touch-callout: none;
}

Для Firefox я пока не нашел простого решения.

Обновление 2

Для Firefox я сейчас пришелсо следующим решением для обезьяны:

(function() {
    var origClosest = SVGElement.prototype.closest;
    SVGElement.prototype.closest = function (sel) {
      var c = origClosest.apply(this, arguments);
      if(c && sel === 'a' && c.namespaceURI === this.namespaceURI) {
        return c.parentNode && c.parentNode.closest(sel);
      } else {
        return c;
      }
    };
  })();

Я переопределяю метод closest (который сам Firefox использует для поиска затронутых <a>) в SVG-элементах с помощью моего собственного метода, который пропускает все <a> элементы, принадлежащие пространству имен SVG.

Дополнительно я представил выпуск в репозитории Firefox на Github и выпуск для Chromium.

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