Avatar for the PupilTong user
PupilTong
Paws
BlogDocsChangelog

Performance History

Latest Results

Add edge-case unit tests + WPT translation for Layer clipping Addresses the gap that the previous commit covered the happy path only. Additional Rust unit tests under `renderer::tests`: - `test_layer_kind_emits_clip_op_for_longhand_mixed_clip_keywords` — exercises the longhand path with `overflow-x: hidden` + `overflow-y: clip` (mixed clip-style keywords). Avoids the spec's `visible → auto` coercion that fires when only one axis is non-visible. - `test_layer_kind_clip_op_fires_on_transition` — confirms a Layer with default `visible` overflow emits no clip op on its first frame, and a re-rendered tree with `overflow: hidden` emits the Layer's own clip op alongside the root View's baseline. - `test_multiple_layer_children_emit_clip_ops_independently` — three sibling Layer-kind children with `hidden`, `visible`, `clip` overflow. Asserts exactly 3 clip ops total (root + two clipped children); the visible child must not emit one. WPT translation: - New `paws-wpt/fixtures/css-overflow-layer-clipping/` Yew fixture mounts three classed `<div>`s (`.hidden`, `.clip`, `.visible`) under a flex parent, applying overflow via longhand declarations through the compile-time `css!()` pipeline. - New `paws-wpt/tests/css_overflow.rs` host runner drives the iOS renderer's `ViewTree::process` against the wasm-executed fixture and asserts the emitted op-tag stream: three `DeclareLayer`s, no `DeclareScrollView`s, exactly three `SetClipsToBounds` ops (root View baseline + two clipped Layers). - The runner reaches the iOS renderer via a new `pub mod test_support` in `ios-renderer-backend` that re-exports `IosNodeState` and a `process_into_op_tags` wrapper. `OpBuffer::op_count` and `OpBuffer::tag_at` lose their `#[cfg(test)]` gate so the support module compiles in non-test builds; visibility stays `pub(crate)`. - `paws-wpt/Cargo.toml` gains `ios-renderer-backend` as a dev-dependency. `paws-wpt/build.rs` registers the new fixture. - `wpt-alignment.md` updated: new `css/css-overflow/` section row documenting the renderer-side translation of the upstream `overflow-clip-rendering-001.html` / `overflow-hidden-rendering-001.html` reftests; summary count 1 → 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude/pr2-layer-clipping
5 hours ago
Honour overflow: hidden|clip on CALayer-backed nodes (iOS renderer) A non-root, non-scrollable element renders as `ViewKind::Layer` in the iOS renderer (see `determine_kind` at `renderer.rs:358-387`). Today the clip-emission path at `renderer.rs:273` and the initial-emit path in `emit_full_node` at `renderer.rs:339` both filter Layer kind out, so `overflow: hidden | clip` on a layer-backed element is silently ignored — the descendant content is drawn unclipped past the box's bounds. This PR fixes that asymmetry. The Rust side now emits the `SetClipsToBounds` op for Layer kind too, and the Swift `OP_SET_CLIPS` handler dispatches on the underlying object type: `UIView.clipsToBounds` for View / ScrollView, `CALayer.masksToBounds` for Layer. The two are independent UIKit knobs but have identical clip-descendants-to-bounds semantics, which is what CSS Overflow Level 3 mandates for `overflow: hidden` and `overflow: clip` (<https://drafts.csswg.org/css-overflow/#overflow-properties>). The `emit_full_node` path for Layer skips the op when `clips == false` because `masksToBounds` defaults to `false` on a fresh `CALayer`, making the explicit-false op redundant. The dirty-check path still fires whenever a Layer transitions between clip states across frames. Tests (added under `renderer::tests`): - `test_layer_kind_emits_clip_op_for_overflow_hidden` — confirms a Layer-kind child with `overflow: hidden` produces both DeclareLayer and SetClipsToBounds ops. - `test_layer_kind_emits_clip_op_for_overflow_clip` — same for the `clip` value, mirroring `has_clip_overflow`'s shared treatment. - `test_layer_kind_overflow_visible_does_not_emit_clip_op` — guards against a future refactor accidentally emitting clip ops for the default `visible` case on Layer kind. The Swift change mirrors the existing UIView-or-CALayer dispatch pattern used for `OP_SET_BG_COLOR` at `OpExecutor.swift:148-154`, so it follows established convention. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude/pr2-layer-clipping
9 hours ago
Replace Stylo fallback with direct token → typed-value shorthand expansion Per review: transforming `ArchivedCssToken` into a CSS string and re-parsing through `style::parse_one_declaration_into` is not allowed. The IR's archived tokens must produce Stylo typed values directly with no parser invocation. Removed (this commit): - `helpers::tokens_to_css_string` and its `archived_unit_as_str` / `needs_separator_between` / `emit_token` support functions. - `mod::stylo_parse_raw_into_block` (the generic Stylo-backed Raw fallback that did the string round-trip). - Engine tests for properties that only worked through the generic fallback (`margin` / `padding` shorthand, `background-color` / `opacity` longhands). Added (this commit): - `keyword::convert_overflow_shorthand_into_block` — a direct `&[ArchivedCssToken]` walker that recognises the 1-or-2 keyword shorthand grammar from CSS Overflow 3 §2.1 and pushes `PropertyDeclaration::OverflowX` + `OverflowY` into the rule block. Reuses the same five-keyword table as the longhand `ir_to_overflow` via a shared `parse_overflow_keyword(&str) -> Overflow` helper. - `mod::convert_style_rule` dispatches `Raw` declarations whose name is `Overflow` to the shorthand expander before falling through to the single-declaration `convert_declaration` path. Pattern is the canonical hook for adding future shorthands. - A new test (`test_ir_overflow_shorthand_non_ident_token_drops`) covering the "non-keyword token invalidates the whole declaration" branch of the direct expander. The IR wire format is unchanged. No `core::fmt::Write` / no string intermediate / no `parse_one_declaration_into` call sits anywhere on the Raw path. Module + fixture doc-comments updated to reflect the direct-from-tokens architecture. Gates: 319 engine tests pass (was 322 before this commit because generic-fallback-dependent tests for margin / padding / background-color / opacity were removed), WPT `overflow_shorthand_expands_to_longhands` still passes, `cargo clippy --all-features -- -D warnings` clean on all Paws crates, `cargo fmt --check` clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude/beautiful-edison-c29ab9
21 hours ago
Generic Stylo-backed Raw fallback for the CSS IR pipeline Adds a single fallback hook that hands any `PropertyValueIR::Raw` declaration the bespoke converters don't recognise to Stylo's `parse_one_declaration_into`, the same parser the inline-style path already uses. Shorthand expansion and value validation then come for free for every property Stylo can compute. The originating motivation is CSS Overflow Level 3 (https://drafts.csswg.org/css-overflow/#overflow-properties): the shorthand `overflow: hidden` / `overflow: hidden scroll` was silently dropped on the `css!()`-compiled IR pipeline (longhands were already typed and worked). The same gap existed for every other CSS shorthand (margin / padding / border / font / background / flex / grid / …) and for every longhand the bespoke `convert_raw_declaration` path lists as "not yet supported" (color, background-color, opacity, font-*, text-*, align-*, justify-*, grid-*, border-*-color, border-*-radius). All of those now apply, exercised by new engine and WPT tests. The IR wire format is unchanged. The new path stringifies archived `CssToken`s back to CSS source text (a single space separator is inserted between adjacent tokens because `parse_tokens` uses `cssparser::next()` which drops whitespace tokens), then routes through Stylo's standard parser context. For shorthands Stylo expands into 2+ longhand `PropertyDeclaration`s which are pushed at the original importance. WPT: `parsing/overflow-shorthand.html` + `parsing/overflow-computed.html` slice — translated as `paws-wpt :: css_overflow :: overflow_shorthand_expands_to_longhands`. Engine-level coverage at `engine/src/runtime.rs :: test_ir_overflow_shorthand_*` exercises the keyword cross-product through the same pipeline; coverage extends to `margin`, `padding`, `background-color`, and `opacity` to confirm the fallback is not overflow-specific. `wpt-alignment.md` updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude/beautiful-edison-c29ab9
1 day ago
Introduce paws-wpt: WPT conformance via the Yew fork (#111) ## Summary - Adds the `paws-wpt` workspace member: a small `testharness` assertion vocabulary, a `build.rs` that compiles standalone `wasm32-wasip2` fixtures, and host-side runner tests that load each fixture through `paws-runner` and assert on engine state. - First translated test: `dom/nodes/Document-createElement.html` — HTML-document `<div />` slice. `html! { <div /> }` is asserted to produce a Paws element with `localName == "div"` and `namespaceURI == HTML_NS`. - Adds [`wpt-alignment.md`](wpt-alignment.md) (the per-spec tracker) and updates `agents.md` with a "WPT Alignment" section locking in (a) **Yew flavor only** — no parallel direct-binding translations, (b) every PR description must include the alignment status block (this PR, and all subsequent). - Adds the upstream WPT clone as a gitignored `wpt-reference/` directory — read-only spec corpus. Paws will not embed a JavaScript engine, so WPT is treated as a corpus of expected behaviors that we hand-translate, not as something we execute. ## WPT alignment status | Status | Count | | --- | --- | | Translated (Yew flavor passing) | 1 | | In progress | 0 | | Skipped (with reason) | 0 | | Not started | n/a | Pinned upstream snapshot: [`e04cee8384c069f6bb7dd54f920ef9395a5e22f5`](https://github.com/web-platform-tests/wpt/commit/e04cee8384c069f6bb7dd54f920ef9395a5e22f5) ### dom/nodes/ | WPT path | Paws Rust test | Status | Reason / notes | | --- | --- | --- | --- | | `Document-createElement.html` | `paws-wpt :: dom_nodes :: create_element_div_in_html_document` | translated | HTML-document `<div />` slice only. Mixed-case / invalid-name / XML-doc subtests are out of scope under "Yew flavor only" — see fixture docs at `paws-wpt/fixtures/dom-nodes-document-create-element/src/lib.rs`. | ## Test plan - [x] `cargo test -p paws-wpt --test dom_nodes` — `1 passed; 0 failed` - [x] `cargo fmt --check` - [x] `cargo clippy -p paws-wpt --all-targets --all-features -- -D warnings` - [ ] `cargo test --all` — not run locally (would re-execute the full e2e suite); CI will exercise it 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
1 day ago
docs: rewrite README as AI-native introduction (#112) ## Summary - Replace the badge-only README with a full project intro: thesis, ASCII architecture diagram, crate map, and the standard CLI commands kept as a fallback table. - Add an **AI-native usage** section: copy-paste prompts grouped by task (Orienting, Building & checking, Authoring UI, Running on iOS, Performance work) that an agent in this repo can act on directly, using the existing `CLAUDE.md` / `agents.md` grounding plus the bundled skills (`ios-simulator-debug`, `codspeed-optimize`). - Cover the "host can't mutate the UI tree" design constraint and the Stylo/Taffy/Yew layering so a first-time reader gets the technical thesis without spelunking through `agents.md`. ## Why The previous README was a single CodSpeed badge — new contributors (and the AI assistants the repo is built around) had nothing to anchor on. This rewrite gives both audiences a way in: humans get prose + a diagram + commands, agents get prompts that match the skills and workflows already wired into the repo. ## Test plan - [ ] Render the README on GitHub and confirm the badges, ASCII diagram, and tables display correctly - [ ] Verify every relative link in the crate map and "How the Agents Stay in Sync" sections resolves - [ ] Pick one prompt from each AI-native section and sanity-check that it maps to real files / skills in this branch 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
main
2 days ago

Latest Branches

CodSpeed Performance Gauge
+20%
iOS renderer: honour overflow: hidden|clip on CALayer-backed nodes#114
5 hours ago
9d59dc1
claude/pr2-layer-clipping
CodSpeed Performance Gauge
0%
Generic Stylo-backed Raw fallback for the CSS IR pipeline#113
21 hours ago
c870a2e
claude/beautiful-edison-c29ab9
CodSpeed Performance Gauge
0%
docs: rewrite README as AI-native introduction#112
2 days ago
dc8bdea
claude/modest-jemison-24c55a
© 2026 CodSpeed Technology
Home Terms Privacy Docs