From a6afb4ad2bd6e3bf9733fe74a8bd2dd7c7bfc633 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Sun, 31 May 2026 21:34:43 +0300 Subject: [PATCH] fix(browser): null-guard pageError.location in playwright bundle (#915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avito pages emit uncaught JS errors without a location (ad / cross-origin scripts); playwright 1.60.0's dispatcher reads pageError.location.url with no null-guard (coreBundle.js ×2: BrowserContextDispatcher + trace event) → TypeError 'Cannot read properties of undefined (reading url)' crashes the node-driver protocol connection → 'Connection closed while reading from the driver' / TargetClosedError → tradein-browser returns 500 and server.py does a full browser relaunch. Proven on prod run_32: ~6/21 /fetch hit 500, each forcing a ~5-10s relaunch and stalling the city-sweep. playwright upgrade is impossible — camoufox 0.4.11 pins the matching Firefox+juggler build. Patch the pinned bundle in-image: pageError.location.{url,lineNumber,columnNumber} -> optional chaining (no-op when location is present). Build asserts >=2 sites patched, failing loudly on a future playwright bump. Verified against the deployed bundle: 2 unguarded -> 2 guarded, 0 remaining, node --check OK. Refs #883, #901, #916 --- tradein-mvp/browser/Dockerfile | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tradein-mvp/browser/Dockerfile b/tradein-mvp/browser/Dockerfile index 689db9f8..e8239d08 100644 --- a/tradein-mvp/browser/Dockerfile +++ b/tradein-mvp/browser/Dockerfile @@ -23,6 +23,28 @@ WORKDIR /app # camoufox[geoip] тянет playwright как зависимость RUN pip install --no-cache-dir "camoufox[geoip]" aiohttp +# ── #915: null-guard для pageError.location в playwright 1.60.0 ───────────────── +# Firefox/juggler-бэкенд иногда отдаёт uncaught JS-ошибку страницы (реклама / +# cross-origin скрипты на avito) БЕЗ поля location. playwright-диспетчер при +# доставке pageError-события читает `pageError.location.url` (coreBundle.js, +# 2 места: BrowserContextDispatcher + trace event) без null-guard → +# `TypeError: Cannot read properties of undefined (reading 'url')` ВНУТРИ +# event-хэндлера node-драйвера → рвёт protocol-соединение → "Connection closed +# while reading from the driver" / TargetClosedError → server.py отдаёт 500 и +# делает полный relaunch браузера (дорого, тормозит sweep). Недетерминированно: +# зависит от того, кинет ли конкретная загрузка locationless-ошибку. +# Апгрейд playwright невозможен — camoufox 0.4.11 pinned под конкретный +# Firefox+juggler. Чиним optional-chaining'ом прямо в pinned-бандле: +# `pageError.location.X` → `pageError.location?.X` (no-op когда location есть; +# отдаёт {url:undefined,...} когда нет → событие доставляется без краша). +# Сборка падает (exit 1) если паттерн не найден — сигнал что bump playwright +# сломал патч. +RUN PW_BUNDLE="$(python -c 'import os,playwright;print(os.path.join(os.path.dirname(playwright.__file__),"driver","package","lib","coreBundle.js"))')" \ + && sed -i -E 's/pageError\.location\.(url|lineNumber|columnNumber)/pageError.location?.\1/g' "$PW_BUNDLE" \ + && N="$(grep -cF 'pageError.location?.url' "$PW_BUNDLE")" \ + && echo "tradein-browser: patched pageError.location?.url sites: $N" \ + && [ "$N" -ge 2 ] + COPY server.py ./server.py # camoufox fetch качает (а) Firefox-сборку и (б) GeoLite2 mmdb (geoip=True).