Sentry-javascript: Menginstruksikan EventTarget.prototype.addEventListener menyebabkan masalah di Chrome

Dibuat pada 14 Mei 2019  ·  28Komentar  ·  Sumber: getsentry/sentry-javascript

Paket + Versi

  • [X] @sentry/browser 5,2,0

Deskripsi

Kami mendapatkan kesalahan ini:

Cannot convert undefined or null to object

Sepertinya yang terjadi di sini, menurut Chrome:

https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/integrations/trycatch.ts#L88

Inilah jejak tumpukan:

Screen Shot 2019-05-14 at 10 54 20 AM

Berikut cuplikan dari kesalahan di Chrome DevTools:

Screen Shot 2019-05-14 at 10 56 18 AM

Sepertinya OpenLayers memberikan kesalahan, tetapi Sentry tidak menanganinya dengan benar dan membuat kesalahan itu sendiri.

Help Wanted Needs Reproduction

Komentar yang paling membantu

Juga, @kamilogorek , menurut saya masalah ini harus dibuka kembali.

Semua 28 komentar

Saya juga menemukan kesalahan ini. Ini kadang-kadang terjadi saat memanggil fungsi global addEventListener atau removeEventListener , mis:

addEventListener("someevent", callback)

Memanggilnya dengan "parameter ini" menyelesaikan masalah:

window.addEventListener("someevent", callback)

Sayangnya, saya tidak mereproduksinya secara konsisten. Satu-satunya hal yang dapat saya pikirkan adalah bahwa dalam kasus pertama, this adalah undefined (karena mode "use strict" ), dan dalam kasus selanjutnya, this akan menjadi window .

Saya menggunakan @sentry/[email protected] . Tampaknya hanya terjadi pada versi Chrome / Chromium terbaru (74.0.3729 dan 75.0.3770, lihat detail di bawah). Fakta "menyenangkan" adalah: kesalahan ini dilaporkan cukup sering, jadi ini adalah alasan utama kuota acara Sentry saya habis.

EDIT: bergabung dengan tangkapan layar dari daftar rinci browser yang terkena dampakScreenshot_20190516_194938
Seperti yang Anda lihat, tampaknya ini dimulai dari Chrome 74.0.3729, yang telah keluar sejak 23 April.

Ini hanya terjadi saat kami menggunakan OpenLayers untuk membuat peta baru. Akibatnya, saya telah memutuskan untuk membuang OL untuk Leaflet (mungkin langkah yang baik secara umum), dan saya hanya berharap ini menyelesaikan masalah saya.

Saya berhasil menulis program minimal untuk mereproduksi ini secara konsisten. Jalankan saja di devtools konsol Anda:

const original = EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener = function (eventName, fn, options) {
  "use strict"
  original.call(this, eventName, fn, options)
}

for (var i = 0; i < 100000; i += 1) {
  if (i % 100 === 0) console.log(i)
  addEventListener("mouseup", () => {})
}

Dalam kasus saya, itu melempar setelah iterasi ke 4600.

Pada catatan semi terkait, ketika saya menghapus Sentry, LogRocket tersandung dengan cara yang sangat mirip.

@BenoitZugeyer @ffxsam terima kasih atas kasus repro. Setelah penyelidikan lebih lanjut, saya dapat mengetahui bahwa ini bukan masalah SDK kami, ini hanya batasan Chrome untuk event listener per objek.

Ketika Anda memanggil repro di atas pada halaman manapun (baik itu http://example.com), itu juga akan rusak. Tidak ada SDK yang dibutuhkan.

listeners-repro

Ya, ini adalah masalah Chrome. Tetapi memasukkan SDK Anda memicu masalah itu, melanggar kode kami. Beruntung bagi saya ini mudah diperbaiki di basis kode saya, tetapi saya akan sedikit kesal jika terjadi dalam ketergantungan seperti @ffxsam

@BenoitZugmeyer bagaimana bisa begitu? Kami _don't_ menambahkan pendengar kami sendiri. Kami hanya mencegat panggilan pengguna ke addEventListener . Jika Anda tidak menyebutnya, kami tidak akan melakukannya.
Dan masalahnya tidak dipicu oleh kami, tetapi dilaporkan dari basis kode kami, karena di sinilah tempat pemanggilan asli berakhir.

Pada dasarnya, di SDK Anda, Anda melakukan ini untuk mencegat panggilan addEventListener :

const original = EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener = function (eventName, fn, options) {
  "use strict"
  original.call(this, eventName, fn, options)
}

Menghapus baris tersebut dari cuplikan yang saya berikan kepada Anda (artinya: menghapus SDK Anda di kode saya) memperbaiki masalah: kita dapat menambahkan event listener sebanyak yang diperlukan. Jadi tentu saja Anda tidak menambahkan pendengar sendiri, tetapi bug Chrome dipicu oleh cara Anda mencegat panggilan addEventListener .

@BenoitZugmeyer Anda ada di sini, saya buruk. Itu karena mode ketat yang disebutkan. Satu-satunya hal yang dapat kami lakukan di sini adalah menonaktifkan, lalu semuanya berfungsi dengan baik 🤷‍♂

const original = EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener = function (eventName, fn, options) {
  original.call(this, eventName, fn, options)
}

for (var i = 0; i < 100000; i += 1) {
  if (i % 100 === 0) console.log(i)
  addEventListener("mouseup", () => {})
}

Saya rasa Anda juga bisa melakukan sesuatu seperti original.call(this || window, ...) . Mode ketat tidak ditambahkan dalam fungsi seperti di cuplikan saya, tetapi di file dist yang dihasilkan oleh penyiapan build Anda.

this || window secara efektif akan mengubah perilaku kode pengembang, jadi saya tidak yakin tentang yang satu ini.
use strict memiliki cakupan fungsi, dan karena bundle.js mendefinisikannya di bagian paling atas (baik, TypeScript melakukannya untuk kami), ini juga memengaruhi metode pembungkusan yang disebutkan di atas:

/*! @sentry/browser 5.2.1 (a5b87c1e) | https://github.com/getsentry/sentry-javascript */
var Sentry = (function (exports) {
    'use strict';

Meskipun this || window memperbaiki masalah jadi ...: S dan seperti 99,9% kasus penggunaan yang berasal dari jendela proto.

Saya melaporkan masalah tersebut di sini: https://bugs.chromium.org/p/chromium/issues/detail?id=964249

Saya pikir itu tidak akan mengubah perilaku kode karena memanggil fungsi asli addEventListener dengan undefined tampaknya setara dengan memanggilnya dengan objek global. Tetapi saya mungkin tidak memikirkan semua kasus di sana ...

Keren terima kasih! Dan sementara itu https://github.com/getsentry/sentry-javascript/pull/2078

EDIT: menemukan solusi yang lebih bersih:

Sentry.init({
    ...
    // XXX: Workaround for https://github.com/getsentry/sentry-javascript/issues/2074
    defaultIntegrations: Sentry.defaultIntegrations.filter(({ name }) => name !== 'TryCatch'),
});

barang lama

Saya memilih solusi ini untuk saat ini.

EventTarget.prototype.addEventListener = EventTarget.prototype.addEventListener.__sentry_original__;
EventTarget.prototype.removeEventListener = EventTarget.prototype.removeEventListener.__sentry_original__;

Masalah ini menyebabkan cukup banyak kebisingan bagi kami: Puluhan ribu peristiwa per jam, total ~ 1,8 juta. Menantikan perbaikan. 😬

Screen Shot 2019-05-20 at 11 22 24 AM

@javan memperbaiki tes PR yang tertunda, kami akan merilis patch minggu ini.

Saya masih melihat ini di @sentry/[email protected] .

Menjalankan cuplikan ini di konsol tetap melempar ketika penjaga diaktifkan.

for (var i = 0; i < 100000; i += 1) {
  if (i % 100 === 0) console.log(i)
  addEventListener("mouseup", () => {})
}

Sama. Masalah masih ada di v5.3.0.

Contoh: https://sentry-browser-chrome-bug.glitch.me
Sumber: https://glitch.com/edit/#!/sentry -browser-chrome-bug? Path = src / main.js: 18: 0


Screenshot

Screen Shot 2019-05-24 at 8 39 53 PM


Tampaknya menggunakan apply() alih-alih call() dapat mengatasi masalah ini. Tidak yakin apakah ini solusi yang layak untuk implementasi Sentry.

Misalnya, cuplikan ini menggelitik bug Chrome:

const original = EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener = function(eventName, fn, options) {
  "use strict"
  original.call(this, eventName, fn, options)
}

let count = 0
while (count++ < 10000) addEventListener("click", console.log)

Yang ini tidak:

const original = EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener = function() {
  "use strict"
  original.apply(this, arguments)
}

let count = 0
while (count++ < 10000) addEventListener("click", console.log)

Juga, @kamilogorek , menurut saya masalah ini harus dibuka kembali.

Selesai. Meskipun saya perlu waktu untuk melihatnya, karena saya sibuk dengan pekerjaan lain. Setiap bantuan dihargai :)

17 Mei 2019
Saya melaporkan masalah tersebut di sini: https://bugs.chromium.org/p/chromium/issues/detail?id=964249

23 Mei 2019
Masalah Chromium telah ditandai sebagai duplikat dari https://bugs.chromium.org/p/chromium/issues/detail?id=961199 , yang telah ditandai sebagai diperbaiki pada hari yang sama.

13 Maret 2020
Saya ingin tahu apakah ini masih menjadi masalah dengan versi terbaru Chrome / Chromium dan Sentry JS SDK?

Saya belum menemukan penggunaan yang relevan dari "use strict" dalam master, saya membayangkan penerapannya mungkin telah berubah sedikit sejak masalah dilaporkan. Menandai ini sebagai kebutuhan-repro untuk saat ini.

@tokopedia

Kami masih melihat banyak kesalahan yang berasal dari Chrome 74 Seluler.

Menariknya, tidak ada masalah dengan bundle.min.js (dari sentrycdn)
Kami mulai melihat masalah ini ketika kami beralih ke bundle.es6.min.js

Saya kira babel transpile entah bagaimana menghilangkan penggunaan panggilan fungsi buggy di Chrome 74 entah bagaimana

Situs web hole kami hanya menargetkan es6 (es2015) jadi kami berharap dapat menggunakan build es6

image

@Fonger dapatkah Anda memberikan tautan ke acara yang terpengaruh di sini atau langsung ke [email protected]? Terima kasih

@milogor . baru saja diemail

Kami telah melakukan rollback untuk menggunakan bundle.min.js beberapa menit yang lalu.

Hei!

Maaf untuk melakukan plus satu ini tetapi tampaknya kami juga menjumpai ini di codesandbox dan juga ada di tandan:

103711776-6ad73e80-4fb8-11eb-86b7-e902874e30e3

Hal yang menarik adalah hal itu tampaknya hanya terjadi pada chrome di mac

Anda dapat melihat laporan kerusakan yang dibuat pengguna di sini: https://github.com/codesandbox/codesandbox-client/issues/5326

Beri tahu saya jika Anda memerlukan bantuan lain atau apa pun dalam hal ini

Apakah halaman ini membantu?
0 / 5 - 0 peringkat