Commit 1e13eaa
feat(browser): comprehensive engine improvements — rendering, JS, networking, SVG, canvas (#89)
* feat(browser): comprehensive engine improvements — rendering, animation, layout, networking
Paint pipeline:
- CSS filter effects engine (grayscale, invert, sepia, brightness, contrast,
saturate, hue-rotate, opacity) applied to backgrounds and text
- Multi-stop gradient interpolation with banded rendering per stop pair
- True diagonal gradient rendering (per-pixel for arbitrary angles)
- Rounded box shadows (fill_rounded_rect when border_radius > 0)
- Inset box shadow support (edge strips inside padding box)
Animation & transitions:
- Wire TransitionEngine.tick() and AnimationEngine.tick() into frame loop
with Instant-based delta time tracking
- Register @Keyframes animations from UA + author stylesheets on page load
- Active animations/transitions trigger layout invalidation
Layout:
- margin: auto on flex items absorbs free space before justify-content
- tab-size CSS property (parsed, default 8, tabs expanded in pre/pre-wrap)
Networking & security:
- Brotli decompression (Accept-Encoding: gzip, br)
- RFC 6265 cookie path/domain validation with boundary checking
- CSP: style-src, img-src, connect-src directives with default-src fallback
Images:
- WebP format detection (RIFF/WEBP magic bytes)
- loading="lazy" defers image loading after eager images
Developer experience:
- BrowserError API (Network/Parse/Script errors, cleared per navigation)
- Focus indicator (2px blue outline on focused form element)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(browser): JS interactivity, connection pooling, SVG rendering, event dispatch
JavaScript DOM & timers:
- removeChild / insertBefore bindings with JS-side Element.prototype wrappers
- Wire setTimeout/setInterval via existing TimerQueue in oasis-js engine
- Timer callbacks evaluated each tick(), layout marked dirty on fire
Event dispatch:
- mouseover/mouseout dispatched on hover node changes
- keydown + input events dispatched on focused form elements
- All events use bubbling dispatch with stopPropagation support
HTTP connection pooling:
- Thread-local ConnectionPool with per-host reuse (max 2/host, 8 total)
- 30-second idle timeout with stale connection detection
- Changed Connection header from close to keep-alive
- Graceful fallback to fresh connection on pooled stream failure
SVG basic shapes:
- New svg.rs module: parser + renderer for rect, circle, ellipse, line, text
- Color parsing: named colors (21), #RGB, #RRGGBB, rgb(r,g,b), none
- ViewBox scaling for proper coordinate mapping
- Integrated as ReplacedContent::Svg in layout pipeline
- 13 unit tests for SVG parsing and color handling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(browser): fetch API, canvas 2D, radial gradients, form submission, getComputedStyle
JavaScript APIs:
- fetch() with synchronous HTTP GET, thenable response with .text()/.json()
- getComputedStyle() returning ~30 CSS properties via ComputedStyle serialization
- Inline event handlers (onclick, onchange, onsubmit, etc.) auto-registered
- localStorage/sessionStorage backed by in-memory HashMap
- Canvas 2D context: fillRect, strokeRect, clearRect, fillText, beginPath,
moveTo, lineTo, arc, fill, stroke with fillStyle/strokeStyle/lineWidth
CSS rendering:
- radial-gradient() with circle/ellipse shape, multi-stop interpolation
- repeating-linear-gradient() with tiled stop pattern
- RadialGradient type + parser + pixel-by-pixel rendering
Forms & images:
- Form submission on Enter/submit button (GET query string + POST body)
- srcset attribute parsing with width/density descriptor selection
- WebP decoding via optional image crate (behind webp feature flag)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* perf(browser): fix gradient rendering freeze — replace pixel-by-pixel with band-based
Diagonal linear gradients were rendering pixel-by-pixel with O(w*h)
individual fill_rect(1,1) calls, causing multi-second freezes on pages
like Wikipedia. Replaced with axis-snapping approach using a single
fill_rect_gradient call.
Radial gradients similarly replaced: pixel-by-pixel O(w*h) rendering
replaced with concentric rounded-rect bands (max 128 bands), reducing
draw calls from ~130K to ~128 for a typical element.
Fixes app freeze when navigating to https://www.wikipedia.com.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(browser): HTTP keep-alive response hang + performance regression test
The Connection: keep-alive change caused read_response() to block for
the full 15-second READ_TIMEOUT on every request. With keep-alive the
server doesn't close the connection, so reading until EOF hangs.
Fixed by making read_response() content-length-aware: once headers
arrive, it parses Content-Length or detects chunked encoding and stops
reading when the body is complete. Falls back to EOF/timeout only when
neither is present.
Also added an integration test that runs a complex page (with CSS
gradients, tables, nested structure) through the full parse → cascade →
layout pipeline and asserts completion within 500ms.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(browser): back/forward navigation uses cache instead of re-fetching
go_back() and go_forward() previously called navigate_vfs() which
always re-fetches from the network. For HTTPS pages like Wikipedia,
this caused a second TLS handshake + full page download, freezing
the UI.
Added navigate_cached_or_fetch() which checks the in-memory
ResourceCache first. On cache hit for HTML content, re-renders
directly from cached body with zero network latency. Falls back
to navigate_vfs() on cache miss.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(browser): forward button after back, defensive srcset fallback
Forward button was broken because navigate_cached_or_fetch() called
load_html() which calls nav.navigate() — clearing the forward stack.
Added skip_nav_push flag so cache-restored pages don't push new
navigation entries.
Also made srcset URL selection more defensive: filters out empty
and data: URLs before preferring srcset over src, preventing cases
where a bad srcset candidate would suppress the working src URL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(browser): Wikipedia images not loading — 303 redirect + srcset key mismatch
Two bugs prevented most images from loading on Wikipedia:
1. Missing 303 (See Other) in redirect handling. Wikipedia's image CDN
(upload.wikimedia.org) returns 303 redirects for thumbnails. The
browser wasn't following them, receiving empty bodies that failed
to decode. Added 303 to is_redirect().
2. srcset/src URL key mismatch. collect_page_image_requests() stored
decoded images under srcset-derived URLs, but ensure_image_textures()
and assign_textures_recursive() only looked up by elem.src(). When
both attributes were present (nearly all Wikipedia images), textures
were never created. Extracted effective_img_src() helper used
consistently across all three code paths.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(browser): address all Gemini AI review findings + flaky CI test
Fixes all 5 bugs and 2 suggestions from the Gemini code review:
1. Chunked stream parsing false-positive (CRITICAL): Changed from
find_subsequence scanning entire buffer to ends_with checks on
buffer tail, preventing binary data mid-stream from triggering
premature response truncation.
2. CSP bypass in fetch API (CRITICAL): __oasis_fetch now checks
connect-src CSP directives before making HTTP requests. Added
install_document_global_with_csp() that accepts the page CspPolicy.
3. Unsafe JS character escaping (BUG): dispatch_js_key_event now
escapes backslash, single quote, newline, and carriage return
to prevent JS syntax errors on special key presses.
4. Alpha over-accumulation in radial gradients (BUG): Force gradient
band colors to alpha=255 since element-level opacity is handled
separately by apply_opacity at the call site.
5. Stroked arcs silently ignored (BUG): Canvas Arc command now
handles stroke case via stroke_rounded_rect.
6. SVG diagonal lines (SUGGESTION): Diagonal lines now use
Bresenham-like plotting instead of bounding-box fill_rect.
7. Wire repeating-linear-gradient (SUGGESTION): Axis-aligned path
now tiles stop bands when grad.repeating is true.
Also fixes flaky CI test oasis-net::listener_max_connections_reached
by adding retry loop with fresh ports on bind failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address AI review feedback (iteration 2)
Automated fix by Claude in response to Gemini/Codex review.
Iteration: 2/5
Co-Authored-By: AI Review Agent <noreply@anthropic.com>
* fix: address AI review feedback (iteration 3)
Automated fix by Claude in response to Gemini/Codex review.
Iteration: 3/5
Co-Authored-By: AI Review Agent <noreply@anthropic.com>
* fix: resolve CI pipeline failures
Automated fix by Claude in response to pipeline failures.
Failures addressed:
- format
- lint
- test-suite
Actions taken:
- Ran autoformat (ruff format, cargo fmt)
- Fixed remaining lint issues
Iteration: 2/5
Co-Authored-By: AI Pipeline Agent <noreply@anthropic.com>
* fix: address AI review feedback (iteration 5)
Automated fix by Claude in response to Gemini/Codex review.
Iteration: 5/5
Co-Authored-By: AI Review Agent <noreply@anthropic.com>
* fix: resolve CI pipeline failures
Automated fix by Claude in response to pipeline failures.
Failures addressed:
- format
- lint
- test-suite
Actions taken:
- Ran autoformat (ruff format, cargo fmt)
- Fixed remaining lint issues
Iteration: 3/5
Co-Authored-By: AI Pipeline Agent <noreply@anthropic.com>
---------
Co-authored-by: AI Agent Bot <ai-agent@localhost>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: AI Review Agent <ai-review-agent@localhost>
Co-authored-by: AI Pipeline Agent <ai-pipeline-agent@localhost>1 parent 12de3ea commit 1e13eaa
File tree
41 files changed
+3815
-208
lines changed- crates
- oasis-backend-psp
- oasis-browser
- src
- css
- parser
- shorthand
- values
- html
- layout
- block
- loader
- paint
- tests
- oasis-net/src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
41 files changed
+3815
-208
lines changedSome generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
| 118 | + | |
118 | 119 | | |
119 | 120 | | |
120 | 121 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| 26 | + | |
25 | 27 | | |
26 | 28 | | |
27 | 29 | | |
| 30 | + | |
28 | 31 | | |
29 | 32 | | |
30 | 33 | | |
| |||
0 commit comments