fix(browser): pageError.location needs valid defaults, not just optional chaining (#918 follow-up) (#927)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 1m6s
Deploy Trade-In / build-browser (push) Successful in 2m0s

Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
This commit is contained in:
bot-backend 2026-05-31 20:15:39 +00:00 committed by bot-reviewer
parent 0883f6d0f1
commit ecf8add2ce

View file

@ -23,26 +23,33 @@ WORKDIR /app
# camoufox[geoip] тянет playwright как зависимость # camoufox[geoip] тянет playwright как зависимость
RUN pip install --no-cache-dir "camoufox[geoip]" aiohttp RUN pip install --no-cache-dir "camoufox[geoip]" aiohttp
# ── #915: null-guard для pageError.location в playwright 1.60.0 ──────────────── # ── #915/#918: null-guard + ВАЛИДНЫЕ дефолты для pageError.location (playwright 1.60.0)
# Firefox/juggler-бэкенд иногда отдаёт uncaught JS-ошибку страницы (реклама / # Firefox/juggler-бэкенд иногда отдаёт uncaught JS-ошибку страницы (реклама /
# cross-origin скрипты на avito) БЕЗ поля location. playwright-диспетчер при # cross-origin скрипты / anti-bot challenge на avito) БЕЗ поля location.
# доставке pageError-события читает `pageError.location.url` (coreBundle.js, # playwright при доставке pageError-события собирает
# 2 места: BrowserContextDispatcher + trace event) без null-guard → # { url: pageError.location.url, line: ...lineNumber, column: ...columnNumber }
# `TypeError: Cannot read properties of undefined (reading 'url')` ВНУТРИ # (coreBundle.js, 2 места: BrowserContextDispatcher + trace event).
# event-хэндлера node-драйвера → рвёт protocol-соединение → "Connection closed #
# while reading from the driver" / TargetClosedError → server.py отдаёт 500 и # Двухслойный баг (оба рвут protocol-соединение → "Connection closed while reading
# делает полный relaunch браузера (дорого, тормозит sweep). Недетерминированно: # from the driver" / TargetClosedError → server.py 500 + relaunch браузера):
# зависит от того, кинет ли конкретная загрузка locationless-ошибку. # 1. без guard → `pageError.location.url` бросает
# Апгрейд playwright невозможен — camoufox 0.4.11 pinned под конкретный # `TypeError: Cannot read properties of undefined (reading 'url')`;
# Firefox+juggler. Чиним optional-chaining'ом прямо в pinned-бандле: # 2. ОДНОГО optional-chaining (`?.url`) НЕДОСТАТОЧНО (это была дыра #918):
# `pageError.location.X` → `pageError.location?.X` (no-op когда location есть; # url станет undefined, а protocol-валидатор `tString` требует string →
# отдаёт {url:undefined,...} когда нет → событие доставляется без краша). # `ValidationError: location.url: expected string, got undefined`.
# Сборка падает (exit 1) если паттерн не найден — сигнал что bump playwright # Поэтому даём валидные дефолты: url → '', line/column → 0 — проходят валидатор,
# сломал патч. # событие доставляется без краша. Профит: browser возвращает HTML challenge-
# страницы вместо краша → pipeline видит firewall и штатно ротирует IP, а не
# уходит в crash-storm (подтверждено прод-дебагом локального стека 2026-05-31).
#
# Апгрейд playwright невозможен — camoufox 0.4.11 pinned под Firefox+juggler.
# Сборка падает (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"))')" \ 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" \ && sed -i -E "s/pageError\.location\.url,/pageError.location?.url ?? '',/g" "$PW_BUNDLE" \
&& N="$(grep -cF 'pageError.location?.url' "$PW_BUNDLE")" \ && sed -i -E 's/pageError\.location\.lineNumber,/pageError.location?.lineNumber ?? 0,/g' "$PW_BUNDLE" \
&& echo "tradein-browser: patched pageError.location?.url sites: $N" \ && sed -i -E 's/pageError\.location\.columnNumber/pageError.location?.columnNumber ?? 0/g' "$PW_BUNDLE" \
&& N="$(grep -cF "pageError.location?.url ?? ''" "$PW_BUNDLE")" \
&& echo "tradein-browser: patched pageError.location?.url ?? '' sites: $N" \
&& [ "$N" -ge 2 ] && [ "$N" -ge 2 ]
COPY server.py ./server.py COPY server.py ./server.py