Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ permissions:

env:
CGO_ENABLED: "0"
GO_VERSION: "1.26.4"
GO_VERSION: "1.27.1"

jobs:
test:
Expand Down
17 changes: 17 additions & 0 deletions FIDELITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ A survey of how other renderers accelerate loading recommended honouring Retry-A
- **Test**: `TestFetchModuleSourceHonoursRetryAfter` serves 429 with `Retry-After: 1` for the first second. With the fix it succeeds after about 1.0s. Stash-verified: the old code drops the module at 0.46s.
- **Corpus effect**: none measured. The saved Tailwind, Wikipedia and Hacker News renders are pixel-identical before and after, because no module on those pages was rate-limited. The change corrects a case the corpus does not exercise.

## 2026-10-04 (round 162) — Go 1.27.1 becomes the floor; the upgrade surfaced one real test-harness assumption (golden PNGs compared by encoded bytes), now corrected by pixels; govulncheck clean for the code (engine#262, v0.5.0)

Upgrade: `go 1.27.1` in `go.mod`, the CI `GO_VERSION`, the README badge and floor, and the bench module. Go 1.27.1 is the final release (1.27.0 and 1.27.1 are published; 1.27 release candidates are not used).

**Breakages found and what they were**
- **Golden PNGs failed (`TestSVGGolden`, `TestRenderDocumentGolden`)**. The goldens compared the encoded PNG bytes. Go 1.27's DEFLATE chooses different block types, so the same pixels encode to different bytes (2503 vs 2394 bytes). Measured: the SVG golden has 0 differing pixels out of 28000. The golden comparison now accepts the same pixels, decoded; regeneration with `UPDATE_GOLDEN=1` is unchanged. This is a test-harness correction, not a rendering change.
- **gofmt reindents** (the fleet note's first mechanism): a formatting-only change across 23 files, one of which removes a trailing blank line.
- **Coverage**: unchanged floors met (css 99.5, layout 100, paint 100, dom 98.5, paginate 100).

**Security (govulncheck, Go 1.27.1)**
- Code-affected vulnerabilities: 0. The six standard-library findings that the go1.26.4 pin carried are fixed in the new toolchain.
- Module dependency: `github.com/klauspost/compress` v1.17.4 → v1.18.7 (fix for GO-2026-5841). It is an indirect dependency through the browser HTTP transport.
- `golang.org/x/crypto` v0.57.0 has GO-2026-5932, with no fixed release; the code does not call the affected path. It is recorded here, not worked around.
- The SSRF finding from round 161 stands: the library does not filter destinations, and the README and docs say so.

**Release**: minor under 0.x, because the Go floor rises to 1.27.1 for every consumer.

## 2026-10-04 (round 161) — security audit: a 62KB image file could allocate 128MB; raster decode now refuses declared canvases above 25 megapixels; SSRF and toolchain findings recorded (engine#261, patch)

Scope: outbound fetches the engine makes for a page (images, sheets, fonts, modules, fetch/XHR, form posts), the decode path for untrusted bytes, the link hit-map, and the Go toolchain (govulncheck).
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Go Reference](https://pkg.go.dev/badge/github.com/go-webengine/engine.svg)](https://pkg.go.dev/github.com/go-webengine/engine)
[![Docs](https://img.shields.io/badge/docs-mkdocs--material-0079A8)](https://go-webengine.github.io/docs/)
[![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg)](LICENSE)
[![Go 1.26.4+](https://img.shields.io/badge/Go-1.26.4%2B-00ADD8?logo=go)](https://go.dev/dl/)
[![Go 1.27.1+](https://img.shields.io/badge/Go-1.27.1%2B-00ADD8?logo=go)](https://go.dev/dl/)

A pure-Go, **`CGO_ENABLED=0`** headless web engine: it fetches a URL, parses the
HTML into a DOM, applies a real CSS subset (cascade + inheritance + `var()` +
Expand Down Expand Up @@ -226,7 +226,7 @@ paint and paginate 100%, dom 97.4%), which CI fails below and which is raised
paths (root `engine` package, `cmd/render`) are excluded from the gate because
their coverage is not reproducible in CI. The `bench/` fidelity harness is a
separate nested module (it pulls chromedp) and is not in the CGO=0 six-arch CI.
`go.mod` floor is `go 1.26.4`; cross-built for all six 64-bit Go targets.
`go.mod` floor is `go 1.27.1`; cross-built for all six 64-bit Go targets.

## Links

Expand Down
2 changes: 1 addition & 1 deletion bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ engine's `go build ./...` / `go test ./...` from the repo root do **not** see it

## Requirements

- Go 1.26.4+
- Go 1.27.1+
- A Chrome / Chromium binary. Point `CHROME_BIN` at it; default is
`/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`.

Expand Down
8 changes: 4 additions & 4 deletions bench/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/go-webengine/engine/bench

go 1.26.4
go 1.27.1

// Local parent engine module. Keeps chromedp out of the engine's CGO=0,
// 6-arch build and coverage gate.
Expand All @@ -20,7 +20,7 @@ require (
github.com/breml/rootcerts v0.3.7 // indirect
github.com/chromedp/sysutil v1.1.0 // indirect
github.com/dlclark/regexp2/v2 v2.5.2 // indirect
github.com/dop251/goja v0.0.0-20260917113740-793a2a65c13b // indirect
github.com/dop251/goja v0.0.0-20260926152631-39ec2650adc9 // indirect
github.com/evanw/esbuild v0.28.2 // indirect
github.com/go-browserhttp/browserhttp v0.2.0 // indirect
github.com/go-gfx/gfx v0.34.0 // indirect
Expand All @@ -29,7 +29,7 @@ require (
github.com/go-images/jpeg2000 v0.1.0 // indirect
github.com/go-images/png v0.1.0 // indirect
github.com/go-json-experiment/json v0.0.0-20260820222146-c27c302e5fc3 // indirect
github.com/go-opentype/fonts v0.9.1-0.20260907071658-dd9656234a3d // indirect
github.com/go-opentype/fonts v0.10.0 // indirect
github.com/go-opentype/opentype v0.13.1-0.20260927180318-ae6327b14eac // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/go-webengine/esbuildsandbox v0.1.0 // indirect
Expand All @@ -38,7 +38,7 @@ require (
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.4.0 // indirect
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/compress v1.18.7 // indirect
github.com/refraction-networking/utls v1.8.2 // indirect
github.com/sergeymakinen/go-bmp v1.0.0 // indirect
github.com/sergeymakinen/go-ico v1.0.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions bench/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipw
github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=
github.com/dlclark/regexp2/v2 v2.5.2 h1:HAsucWRhsqcDzl6Ua9aR8JwYOTzrZyPrF0/FNxJVAI0=
github.com/dlclark/regexp2/v2 v2.5.2/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU=
github.com/dop251/goja v0.0.0-20260917113740-793a2a65c13b h1:UMDLDHFR1Chu3qnsPNCrVxq0lZgG6JqHpLL5+iqfSkw=
github.com/dop251/goja v0.0.0-20260917113740-793a2a65c13b/go.mod h1:u8yZRUavu+N4EnFFy6J5fVtjE7lEcZ2YyV2GcBXY9c8=
github.com/dop251/goja v0.0.0-20260926152631-39ec2650adc9 h1:Ksd3Vil12b/ykT5NjGzd3qNc688cJB9OUXJZZChEktI=
github.com/dop251/goja v0.0.0-20260926152631-39ec2650adc9/go.mod h1:u8yZRUavu+N4EnFFy6J5fVtjE7lEcZ2YyV2GcBXY9c8=
github.com/evanw/esbuild v0.28.2 h1:A2uETn4jrQTcXaT/shwTDTYBxDjl7fV7nXmUrJxfA2w=
github.com/evanw/esbuild v0.28.2/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
github.com/go-browserhttp/browserhttp v0.2.0 h1:3RcjOQVHgqhSOmI5cfsURpexw/vetoDUoLXKzgTCSac=
Expand All @@ -34,8 +34,8 @@ github.com/go-images/png v0.1.0 h1:OI4yHotS0lA75sLnG2FTL2Vooh4PWpVWEidre1msSe0=
github.com/go-images/png v0.1.0/go.mod h1:V9vaEbr2nrZGorUWn4xv9F24Yuu1/qLVtmailM9GBVo=
github.com/go-json-experiment/json v0.0.0-20260820222146-c27c302e5fc3 h1:UADEEmDKgfXbtnGJZ97beY5XLo9ZechG1nlU4KnRrkE=
github.com/go-json-experiment/json v0.0.0-20260820222146-c27c302e5fc3/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
github.com/go-opentype/fonts v0.9.1-0.20260907071658-dd9656234a3d h1:9WvCVDUtnMBVmviCyC65IGN1Sun3k/goiB7wsp/sbjM=
github.com/go-opentype/fonts v0.9.1-0.20260907071658-dd9656234a3d/go.mod h1:b+o8v1zDZ6B3GixA398jGILAh09+WwfyoYz52zKe7DA=
github.com/go-opentype/fonts v0.10.0 h1:9f7ik795SlBEJjz6iqBE/ZV2PaTauAj537MMWw9t4OQ=
github.com/go-opentype/fonts v0.10.0/go.mod h1:b+o8v1zDZ6B3GixA398jGILAh09+WwfyoYz52zKe7DA=
github.com/go-opentype/opentype v0.13.1-0.20260927180318-ae6327b14eac h1:mpzfJQe1RlF2zawKqvL5poyNdaV6pMbHkK1h+GVLMuM=
github.com/go-opentype/opentype v0.13.1-0.20260927180318-ae6327b14eac/go.mod h1:UjZOTCMtkHheDPzfP0ZghDoQ7wIr6L72T/kuC9Ph1hw=
github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q=
Expand All @@ -54,8 +54,8 @@ github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw=
github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
Expand Down
8 changes: 4 additions & 4 deletions css/external_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ func TestImportURLs(t *testing.T) {
[]string{"x.css"}, []string{""}},
{` @import url( "spaced.css" ) ;`, []string{"spaced.css"}, []string{""}},
{`body{color:red}`, nil, nil},
{`@import ;`, nil, nil}, // no clause
{`@import ;`, nil, nil}, // no clause
{`@import url(unterminated`, nil, nil}, // no semicolon
{`@import url(;`, nil, nil}, // no closing paren before ;
{`@import badtoken.css;`, nil, nil}, // neither url() nor quoted
{`@import "";`, nil, nil}, // empty url
{`@import url(;`, nil, nil}, // no closing paren before ;
{`@import badtoken.css;`, nil, nil}, // neither url() nor quoted
{`@import "";`, nil, nil}, // empty url
{`/* unterminated comment`, nil, nil},
{`@charset "utf-8"`, nil, nil}, // charset without semicolon
}
Expand Down
1 change: 0 additions & 1 deletion css/grid.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,3 @@ func applyGridArea(s *Style, v string) {
s.GridRowEnd = get(2)
s.GridColumnEnd = get(3)
}

8 changes: 4 additions & 4 deletions css/gridflex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,10 @@ func TestParseGridTemplateAreas(t *testing.T) {

func TestParseGridTemplateAreasRejects(t *testing.T) {
for _, v := range []string{
``, // no rows
`"a b" "c"`, // ragged
`"unterminated`, // missing close quote
`"" ""`, // zero columns
``, // no rows
`"a b" "c"`, // ragged
`"unterminated`, // missing close quote
`"" ""`, // zero columns
} {
if got, ok := parseGridTemplateAreas(v); ok {
t.Errorf("areas(%q) unexpectedly ok = %v", v, got)
Expand Down
4 changes: 2 additions & 2 deletions css/selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1084,8 +1084,8 @@ func TestAttributeSelectorGitHubDarkModeBug(t *testing.T) {
// toggle is :checked. With no user interaction the toggle is unchecked, so the
// reveal rule must NOT apply and the menu stays hidden — Chrome's static state.
func TestCheckboxHack(t *testing.T) {
hide, _ := parseComplex(".menu") // display:none base rule
reveal, _ := parseComplex("#toggle:checked ~ .menu") // reveal when checked
hide, _ := parseComplex(".menu") // display:none base rule
reveal, _ := parseComplex("#toggle:checked ~ .menu") // reveal when checked

toggle := checkbox("toggle", "checkbox", false)
menu := el("div", "", "menu")
Expand Down
10 changes: 5 additions & 5 deletions css/value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ func TestParseFontFamily(t *testing.T) {
func TestParseFontFamilyKeepsTheNames(t *testing.T) {
cases := map[string]string{
`'IBM Plex Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif`: "ibm plex sans,helvetica neue,helvetica,arial",
`Spectral, 'Iowan Old Style', Palatino, Georgia, serif`: "spectral,iowan old style,palatino,georgia",
`"IBM Plex Mono", Menlo, monospace`: "ibm plex mono,menlo",
"sans-serif": "",
"serif, sans-serif": "",
` Spectral `: "spectral",
`Spectral, 'Iowan Old Style', Palatino, Georgia, serif`: "spectral,iowan old style,palatino,georgia",
`"IBM Plex Mono", Menlo, monospace`: "ibm plex mono,menlo",
"sans-serif": "",
"serif, sans-serif": "",
` Spectral `: "spectral",
}
for in, want := range cases {
if got := parseFontFamily(in); got.Names != want {
Expand Down
8 changes: 4 additions & 4 deletions dynamic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ func TestLayoutMetricsComputed(t *testing.T) {
n := &dom.Node{Type: dom.Element, Tag: "div"}
st := &css.Style{
Display: css.DisplayBlock, Position: css.PositionRelative,
Margin: css.Edges{Top: 1, Right: 2, Bottom: 3, Left: 4},
Padding: css.Edges{Top: 5, Right: 6, Bottom: 7, Left: 8},
FontSize: 16, FontWeight: 700, Italic: true,
Margin: css.Edges{Top: 1, Right: 2, Bottom: 3, Left: 4},
Padding: css.Edges{Top: 5, Right: 6, Bottom: 7, Left: 8},
FontSize: 16, FontWeight: 700, Italic: true,
LineHeight: css.LineHeight{Px: 24},
Color: css.Color{R: 1, G: 2, B: 3, A: 255},
Background: css.Color{R: 4, G: 5, B: 6, A: 255},
TextAlign: css.AlignCenter, BoxSizing: css.BorderBox,
HasOpacity: true, Opacity: 0.5,
ZIndexAuto: false, ZIndex: 7,
Top: css.Length{Px: 10}, Right: css.Length{Auto: true},
Top: css.Length{Px: 10}, Right: css.Length{Auto: true},
Bottom: css.Length{IsPercent: true, Percent: 0.25}, Left: css.Length{Px: 0},
}
box := &layout.Box{Node: n, X: 0, Y: 0, W: 100, H: 50}
Expand Down
4 changes: 2 additions & 2 deletions engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ func TestRenderDocumentGolden(t *testing.T) {
if err != nil {
t.Fatalf("read golden (run with UPDATE_GOLDEN=1 to create): %v", err)
}
if !bytes.Equal(png, want) {
t.Errorf("render does not match golden fixture.png (%d vs %d bytes)", len(png), len(want))
if !bytes.Equal(png, want) && !samePixels(t, png, want) {
t.Errorf("render does not match golden fixture.png (pixels differ)")
}
}

Expand Down
7 changes: 4 additions & 3 deletions fixtures_checkbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import "testing"
// Vector-2022 dropdowns. Solid-colour blocks only → font-independent bytes.
//
// Row layout (body margin 0, blocks stack):
// A hdr y 0..20 green (0,150,0) ; A menu HIDDEN (unchecked)
// B hdr y 20..40 olive (150,150,0) ; B menu SHOWN y 40..70 red (220,40,40)
// C hdr y 70..90 teal (0,150,150) ; C inv HIDDEN (:not(:checked) matches)
//
// A hdr y 0..20 green (0,150,0) ; A menu HIDDEN (unchecked)
// B hdr y 20..40 olive (150,150,0) ; B menu SHOWN y 40..70 red (220,40,40)
// C hdr y 70..90 teal (0,150,150) ; C inv HIDDEN (:not(:checked) matches)
func TestCheckboxHackGolden(t *testing.T) {
img := renderFixture(t, "checkbox_hack.html", 200, 130)

Expand Down
34 changes: 32 additions & 2 deletions fixtures_position_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"context"
"image"
stdpng "image/png"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -58,11 +59,40 @@ func checkGolden(t *testing.T, img *image.RGBA, name string) {
if err != nil {
t.Fatalf("read golden (run with UPDATE_GOLDEN=1 to create): %v", err)
}
if !bytes.Equal(png, want) {
t.Errorf("render does not match golden %s (%d vs %d bytes)", name, len(png), len(want))
// The contract is the pixels, not the encoder's output: the same pixels
// encode to different bytes when the compressor changes (Go 1.27 picks
// different DEFLATE block types), so compare the decoded images.
if !bytes.Equal(png, want) && !samePixels(t, png, want) {
t.Errorf("render does not match golden %s (pixels differ)", name)
}
}

func samePixels(t *testing.T, a, b []byte) bool {
t.Helper()
ia, err := stdpng.Decode(bytes.NewReader(a))
if err != nil {
t.Fatalf("decode render: %v", err)
}
ib, err := stdpng.Decode(bytes.NewReader(b))
if err != nil {
t.Fatalf("decode golden: %v", err)
}
if ia.Bounds() != ib.Bounds() {
return false
}
bounds := ia.Bounds()
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
r1, g1, b1, a1 := ia.At(x, y).RGBA()
r2, g2, b2, a2 := ib.At(x, y).RGBA()
if r1 != r2 || g1 != g2 || b1 != b2 || a1 != a2 {
return false
}
}
}
return true
}

// TestPositionDemoGolden verifies CSS position relative/absolute/fixed and
// z-index stacking with exact painted-pixel invariants (the fixture uses only
// solid colour blocks, so its bytes are font-independent and byte-golden-safe).
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/go-webengine/engine

go 1.26.4
go 1.27.1

require (
github.com/dop251/goja v0.0.0-20260926152631-39ec2650adc9
Expand Down Expand Up @@ -29,7 +29,7 @@ require (
github.com/go-images/png v0.1.0 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/compress v1.18.7 // indirect
github.com/refraction-networking/utls v1.8.2 // indirect
github.com/sergeymakinen/go-bmp v1.0.0 // indirect
github.com/sergeymakinen/go-ico v1.0.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw=
github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo=
github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M=
Expand Down
12 changes: 6 additions & 6 deletions images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import (
func TestCSSImageSize(t *testing.T) {
// Intrinsic 900x298 (the go.dev Google wordmark shape).
cases := []struct {
name string
st *css.Style
iw, ih int
wantW int
wantH int
wantOK bool
name string
st *css.Style
iw, ih int
wantW int
wantH int
wantOK bool
}{
{"nil style keeps intrinsic", nil, 900, 298, 0, 0, false},
{"no CSS dims keeps intrinsic",
Expand Down
16 changes: 8 additions & 8 deletions js/dynamic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ func TestSessionGeometryReadback(t *testing.T) {
mustHaveJS(t, logs,
"rect=10,20,200,40,210,60,10,20",
"off=200,40,200,40,200,40",
"soff=5,2", // span relative to its offsetParent (the div)
"xoff=0,0,ow=0", // unlaid-out node: zeros, no ancestor rect
"xrect=0", // zero DOMRect
"rects=1,x=0", // d has a rect; x has none
"soff=5,2", // span relative to its offsetParent (the div)
"xoff=0,0,ow=0", // unlaid-out node: zeros, no ancestor rect
"xrect=0", // zero DOMRect
"rects=1,x=0", // d has a rect; x has none
"disp=block,w=186px",
"unknown=[]", // unknown computed property → ""
"pri=[],txt=[]", // priority + cssText inert
"has=true,keys=0", // Has true, Keys empty (read-only view)
"dispAfter=block", // setProperty/removeProperty were no-ops
"unknown=[]", // unknown computed property → ""
"pri=[],txt=[]", // priority + cssText inert
"has=true,keys=0", // Has true, Keys empty (read-only view)
"dispAfter=block", // setProperty/removeProperty were no-ops
)
}

Expand Down
Loading
Loading