Repository navigation
--browser webkit: shoot both sides in WebKit - #156
Merged
Merged
Conversation
WebKit has no CDP, so a shot falls back to page.screenshot({ fullPage,
clip }), tiles kept, and --computed walks without forced states and says
so. WebKit holds fonts.ready, which its screenshot waits on, until the
load event, so a page a stalled frame keeps loading is stopped first.
browser is optional in ResolvedConfig, so a Chromium run's config hash
and capture path are unchanged. A webkit run writes renderdiff-out-webkit
and renderdiff.accepted.webkit.json by default, and merge refuses to mix
engines. The Action takes a browser input; CI installs WebKit.
Closes #150
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
window.stop() fails the page's open requests (a pending fetch rejects, images break), so it is a last resort: the WebKit shot gets 5s, and only past that is the load stopped and the shot retaken, with the side noted as stopped in results.json and the row. GIF docs say "usually" caught as unstable; the Action's browser input is documented as deciding over the config; the rerun refusal names --browser; the missing-WebKit hint names --with-deps. Tests trimmed per review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/engine.ts holds an Engine interface with a chromium and a webkit implementation: output defaults, launch, grab, shot and forced states. capture, run, probe and the CLI resolve it once with engineOf(cfg) and pass it to pageShot, captureTiled and snapshotStates, so isWebKit, the launch branch, browserOf and the out-dir and accepted-file ternaries go. A stalled WebKit shot is no longer retaken: window.stop() lets the shot already in flight finish. Its 5s now covers a whole tiled shot, not each tile. The stopped flag is a local in capture, not a WeakSet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed asset The 5s now spans a whole tiled shot, so a slow finished page was flagged stopped. window.stop() now runs only while the load is open, and that is the flag. A hung or rejected evaluate no longer costs a finished shot. A stopped shot read as clean: broken() ignored it and the note printed only with --progress. It now counts as broken, so it is never clean or reused, shows under the row and in report.html, and evidence.html says Not verified. Like a failed asset it leaves the exit code alone, and a stopped right side isn't recorded for --cache-right. ENGINES goes, for Object.keys(engines), and engine.ts loses comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #150
--browser webkit(orbrowser: "webkit"in the config) shoots both sides in Playwright's WebKit, for CSS that only Safari reads differently. The prefix check from #155 covers the issue's own case, which no WebKit pixel shows. This option covers the cases that do render differently. The newbox-decoration-breakfixture is one: an autofix drops-webkit-box-decoration-break, which gives pixel parity in Chromium and a diff in WebKit.What changes
grab()falls back topage.screenshot({ fullPage: true, clip }). Tiling at 16,384px is kept, sopageShotandcaptureTiledare unchanged. WebKit holdsdocument.fonts.ready, which its screenshot waits on, until the load event; a stalled frame never fires that, so the page iswindow.stop()ped before the shot when it is still loading.--computed.snapshotStatesfalls back to the plain walk, because forcing:hover/:focus-visibleneeds CDP. The run prints one line saying so. Rule coverage and the prefix check are plain JS and work as on Chromium.browseris optional inResolvedConfig(likelottieFrame), so a Chromium run's config hash, and with it--rerun-failed, is unchanged. A WebKit run defaults torenderdiff-out-webkitandrenderdiff.accepted.webkit.json, so its pixel hashes never prune Chromium's entries.mergerefuses to mix engines. The cache key already includes the browser.browserinput (install, cache key, flag, accepted file name) and its self-test gains a WebKit step. CI installschromium webkit.isMobile, and no running both engines in one run.Chromium stays byte-identical
Every WebKit branch is gated on the engine. I ran the whole corpus (60 routes × 2 widths) on main and on this branch, then main against main as a control. In both comparisons the only differences are the fixtures that vary per load by design (
clock,bistable,unsettled,drifting) and the fixture server's port inside failed-asset URLs and error text. Every other PNG and results.json entry is byte-identical.Tests
tests/visual/webkit.test.ts:box-decoration-break: parity in Chromium, a diff in WebKit;flex-vs-gridscores 100% andcolordoesn't;tallis stitched to 18,000px;stalled-frameis shot in normal time;animatedis unstable, not a diff;--computedworks without states and prints the note;--acceptwrites the.webkitfile and leaves Chromium's alone;renderdiff-out-webkit.--browserand config validation;mergerefusing mixed engines.npm testpass, as do the webkit, computed and guardrails visual files. Before the rebase, the controls, equivalence and accepted visual files passed too.🤖 Generated with Claude Code