How to debug ScriptError on line 0 on webview?

喜欢而已 提交于 2019-12-24 16:25:13

问题


I have built a mobile webapp in html/js and I am using the 'window.onerror' to track client side js errors and report them to the server.

Recently I noticed that I receive many reports of ScriptError on line 0.

A quick google search brought me to discussions like Cryptic "Script Error." reported in Javascript in Chrome and Firefox and https://ravikiranj.net/posts/2014/code/how-fix-cryptic-script-error-javascript/

For most people such errors seem to be triggered by failures in scripts that are included from a foreign origin. But unfortunately that's not the case for me.

After many hours of debugging I came up with the following minimal example to reproduce the error:

<!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>

As we can see it's a simple html page with no javascript at all except for the onerror handler itself.

In Safari (ios 12.4.1) no error is triggered. But in both Google Chrome for iOS and Firefox for iOS a ScriptError on line 0 is reported each time the link inside the <svg> element is tapped - but not when tapping the link outside the <svg>. Note that no js event handler is attached to the <svg>.

A live version of the code is online at https://static.laszlokorte.de/scripterror.php

I know that all third party browsers on iOS actually just use safari under the hood extending in with a few custom features. I suspect that those custom features cause the error but I have no idea how to track it down further.

Why does clicking a link inside a plain svg element causes an error in iOS Chrome and Firefox but not in Safari? Is there a way to connect the Safari Webdev tools to mobile browsers other than native Safari?

Update

After taking a deeper look at both the Chrome(iOS) and Firefox(iOS) source code I now found the cause of the problem. Both browsers inject javascript code that runs on touchstart and processes the event's target node. Both browsers check if an '' or '' element has been touched and try to access their their href or src attribute respectively. They both then try to send the attributes values via webkit.postMessage to the host application.

The error seems to be caused by the fact that an <a> element inside an <svg> is actually an SVGAElement and it's href attribute is not a String but an SVGAnimatedString which (other than String) can not be cloned to be sent to another process.

The corresponding code for Firefox can be found here: https://github.com/mozilla-mobile/firefox-ios/blob/826cb396a9eb225b7eb667b47b245e2d98d26ed8/Client/Frontend/UserContent/UserScripts/AllFrames/AtDocumentEnd/ContextMenu.js#L14-L35

The code for Chrome is here: https://github.com/chromium/chromium/blob/master/ios/web/web_state/js/resources/all_frames_context_menu.js#L136-L139

So for Chrome the solution is actually simple because it allows to explicitly opt-out of all this by setting the css property -webkit-touch-callout: none (You can see the check for that in the linked file). For example like this:

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

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

For Firefox I have not found a easy solution yet.

Update 2

For Firefox I now came up with the following monkey patch solution:

(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;
      }
    };
  })();

I override the closest method (that Firefox itself uses to find the touched <a>) on an SVG elements with my own method that skips all <a> elements that belong to the SVG namespace.

Additionally I submitted an issue in the Firefox repo at Github and an issue for Chromium.

来源:https://stackoverflow.com/questions/58088832/how-to-debug-scripterror-on-line-0-on-webview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!