chrome 搞事,下个月全面删除 Event.path

21,781 阅读5分钟

背景

前两天下午,测试同学反馈生产环境有个功能出现异常,然后给我发了张报错截图。 image.png

随后在测试同学的电脑复现并排查问题,通过异常断点,捕捉到异常信息如下: image.png

可以看到异常的原因是 n.path 的值为 undefined,因此 n.path.find 等价于 undefined.find,因此程序报错。其中 n 是一个 Event 实例;path 是事件冒泡经过的节点组成的数组。n.path 有值的情况如下: image.png

Event.path 不是标准属性,常见于 chrome 浏览器,取不到值出现异常不足为奇,只要做个兼容就搞定了,当 Event.path 取不到值时就取 Event.composedPath()。那这是兼容性问题吗,事情好像没有这么简单。仔细对比上述两张截图可以发现,异常时 Event 实例甚至不存在 path 属性,这跟属性存在但值为空是两码事。

进一步排查

好好的 path 属性怎么就不翼而飞了,这是个神奇的问题。当我用自己电脑尝试复现问题时,发现功能正常且无法复现,事情变得更加神奇。两边浏览器都升到了最新版 chrome 108,区别是系统不同,一个是 windows 一个是 macOS。也就是 说同样的代码在同样的软件上跑出了不同结果,这说明可能不是代码或兼容性问题。

为找出真正的原因,我做了几组对照实验,以排除代码、硬件、操作系统和浏览器的影响。情况如下 :

A 组B 组结果
测试同学电脑 win10、chrome 108其他电脑 win10、chrome 108A 组异常,B 组正常
其他电脑 macOS、chrome 108
测试同学电脑 win10、edge 108
测试同学电脑 win10、chrome 104

分析这些结果,出现了更有意思的事:只有一种情况会出现异常,使用测试同学的电脑且浏览器是 chrome 108;当改变电脑、系统、浏览器、浏览器版本等因素时结果都是正常。 也就是说导致异常的因素居然不是单一的,而是多个因素组合(测试同学电脑+chrome+108 版本)产生的结果。

chromium issue 的助攻

从上面的结果看好像没办法再继续排查下去,不过从经验判断,多半是 chrome 又在搞事,这时候可以去 chromium issue 里找找蛛丝马迹,经过一番搜索找到了这条 issue: Issue 1277431: Remove event.pathimage.png

issue 标题很直白,Event.path 将被删除。 从 issue 内容可以看到,这次搞事是从 2021 年 12 月 7 日开始,起因是 chromium 开发团队认为 Event.path 属于非标准 API,会导致 Firefox 等其他浏览器的兼容性问题,于是他们决定将其删除。目前这个变更在 chrome 108 属于灰度阶段,在即将发布的 chrome 109 上会全面应用,webview 则是从 109 版本开始逐步禁用。

变更详情和计划

另外 issue 中提到这个变更会在 console 中进行告警。 image.png

console 中确实有这个告警,不过藏在 console 面板的右上角,不太容易发现,而且需要调用 Event.path 后才会显示。点进去之后会跳转到 Issues 面板并显示详细信息。 image.png image.png

从图中可以看到这个变更属于 Breaking Change,即破坏性变更。另外可以看到变更详情链接版本计划链接。打开变更详情链接可以看到详细的说明、目的、状态、开发阶段等信息。 image.png

打开版本计划链接可以看到,chrome 108 已经在 2022-11-29 正式发布(Stable Release Tue, Nov 29, 2022),chrome 109 将在 2023-01-10 正式发布(Stable Release Tue, Jan 10, 2023)。 image.png

验证

由于英文水平有限,为了避免个人理解存在歧义,使用 chrome 的前瞻版本进行测试,以验证 chrome 108 之后的版本是否真的会应用这个变更。

  • 测试使用的系统为 macOS,浏览器版本包括:chrome-stable(108.0.5359.124)、chrome-beta(109.0.5414.36)、chrome-dev(110.0.5464.2)、chrome-canary(110.0.5477.0)。

image.png

  • 测试代码如下
<!DOCTYPE html>
<html lang="en">
  <head></head>
  <body>
    <script>
      function test() {
        console.log("event.path is:", window.event.path);
      }
    </script>
    <h1 onclick="test()">click me</h1>
  </body>
</html>
  • 测试结果如下

chrome-stable(108.0.5359.124)在 macOS 下 Event.path 有值,结合上文的对照实验中 windows10 下一个有值一个为空。说明 chrome 108 中该变更属于灰度阶段。 image.png

chrome-beta(109.0.5414.36)、chrome-dev(110.0.5464.2)、chrome-canary(110.0.5477.0)在 macOS 下 Event.path 都为空,说明 chrome 109 之后全面删除了 Event.path 属性。 image.png

解决方案

先看影响范围,从项目维度来看,所有前端项目都可能受到影响;从代码维度来看,项目源码和第三方依赖都可能受影响。在 github 中搜索发现 swipperopenlayers 等第三方库中都有相关 issue。因此解决方案需要全面考虑:最好对所有项目都进行排查修复,另外不仅要排查源码,还要考虑第三方库。

根据官方建议及综合考虑,推荐在前端项目中统一添加如下 polyfill 代码:

  Object.defineProperty(Event.prototype, "path", {
    get() {
      return this.composedPath();
    },
  });

最后

chrome 109 预计在 2023-01-10 正式发布,届时会全面禁用 Event.path,所有源码中使用该属性或第三方库使用该属性的前端项目都可能会出现异常,还有 20 几天时间,建议尽快排查修复。

一些经验

  • 关注 devtools 中的 console、issue 等各种告警信息,有助于调试和排查问题、以及发现潜在的问题
  • 关注 chorme 迭代计划,有条件可以做前瞻性测试,预防未来可能发生的异常

image.png