CSS Layout Engine that implements Box/Flex/Grid
| Module | Passed | Total | Rate |
|---|---|---|---|
| Flexbox | 543 | 609 | 89.2% |
| Block | 204 | 226 | 90.3% |
| Grid | 268 | 331 | 81.0% |
| Total | 1015 | 1166 | 87.0% |
| Module | Passed | Total | Rate |
|---|---|---|---|
| CSS Parser | 332 | 332 | 100% |
| CSS Selector | 62 | 62 | 100% |
| CSS Media Query | 41 | 41 | 100% |
| Module | Passed | Total | Rate |
|---|---|---|---|
| css-flexbox | 282 | 289 | 97.6% |
| css-grid | 32 | 33 | 97.0% |
| css-tables | 30 | 32 | 93.8% |
| css-display | 79 | 79 | 100.0% |
| css-box | 30 | 30 | 100.0% |
| css-sizing | 83 | 94 | 88.3% |
| css-align | 37 | 44 | 84.1% |
| css-position | 83 | 84 | 98.8% |
| css-overflow | 214 | 243 | 88.1% |
| css-contain | 283 | 303 | 93.4% |
| css-variables | 107 | 107 | 100.0% |
| filter-effects | 98 | 106 | 92.5% |
| compositing | 2 | 2 | 100.0% |
| css-logical | 5 | 5 | 100.0% |
| css-content | 1 | 2 | 50.0% |
| css-multicol | 4 | 4 | 100.0% |
| css-break | 26 | 27 | 96.3% |
| Total | 1396 | 1484 | 94.1% |
| Site | Diff | Status |
|---|---|---|
| example.com | 1.16% | PASS |
| info.cern.ch | 3.30% | PASS |
| www.google.com | 3.80% | PASS |
| news.ycombinator.com | 12.4% | WARN |
| en.wikipedia.org | 7.65% | WARN |
just vrt-url-native https://example.com # Compare any URL
just test-wpt-vrt # WPT visual regression
CRATER_PAINT_BACKEND=native just test-vrt # Full VRT suite| Suite | Passed | Total | Rate |
|---|---|---|---|
| DOM WPT (wpt/dom/nodes) | 9296 | 9296 | 100.0% |
| WebDriver BiDi strict | 277 | 277 | 100.0% |
| WebDriver BiDi session | 130 | 130 | 100.0% |
| WebDriver BiDi browsing_context | 1008 | 1008 | 100.0% |
| WebDriver BiDi script | 1025 | 1025 | 100.0% |
| WebDriver BiDi input | 708 | 708 | 100.0% |
| WebDriver BiDi network | 1389 | 1389 | 100.0% |
npm run wpt:fetch-all # Fetch all WPT tests
npm run wpt:run-all # Run all WPT testsjust wpt-dom-all
just wpt-webdriver-profile strict
just wpt-webdriver session
just wpt-webdriver browsing_context
just wpt-webdriver script
just wpt-webdriver input
just wpt-webdriver network# Text module (mizchi/text-compatible or measureText(text, fontSize) module)
CRATER_TEXT_MODULE=/abs/path/to/text-module.js \
CRATER_TEXT_FONT_PATH=/abs/path/to/font.ttf \
npx tsx scripts/wpt-runner.ts css-overflow
# Image module patterns:
# - module itself as function, or resolveImageIntrinsicSize(src) / getImageSize(src) / sizeOf(src)
# - dimensions/getDimensions/metadata/identify/probe/readHeader/imageInfo style functions
# - image-size style functions that accept src, resolved local path, Uint8Array, or Buffer
# - nested namespace exports such as default.image.getImageSize or default.metadata.identify
# - result shapes: {width,height}, [width,height], {dimensions:{width,height}}, {columns,rows}, {shape:[height,width,...]}
# - mizchi/image-style decode_image_stream(bytes) / decode_png(bytes)
# - synchronous callback providers are supported; Promise/stream-only providers are not yet supported
CRATER_IMAGE_MODULE=/abs/path/to/image-module.js \
npx tsx scripts/wpt-runner.ts css-contain
# Optional local file resolver fallback for images (off by default)
CRATER_IMAGE_FILE_RESOLVE=1 \
npx tsx scripts/wpt-runner.ts wpt/css/css-contain/contain-size-021.htmlnpx tsx scripts/wpt-runner.ts --list# Example: generate per-shard reports
mkdir -p /tmp/wpt-reports
npx tsx scripts/wpt-runner.ts css-overflow css-grid css-tables --workers 4 --json /tmp/wpt-reports/wpt-css-shard-1.json
npx tsx scripts/wpt-dom-runner.ts --dom --json /tmp/wpt-reports/wpt-dom-dom.json
npx tsx scripts/wpt-dom-runner.ts --svg --json /tmp/wpt-reports/wpt-dom-svg.json
npx tsx scripts/wpt-webdriver-runner.ts --subset --json /tmp/wpt-reports/wpt-webdriver-strict.json
# Optional: network sweep profile (non-gating, excludes auth-related paths)
npx tsx scripts/wpt-webdriver-runner.ts --profile network-no-auth --json /tmp/wpt-reports/wpt-webdriver-network-no-auth.json
# Aggregate compatibility summary
npx tsx scripts/wpt-ci-summary.ts --input /tmp/wpt-reports --json /tmp/wpt-summary.json --markdown /tmp/wpt-summary.md
# Analyze CI run timing from GitHub Actions run jobs API output
gh api repos/mizchi/crater/actions/runs/<RUN_ID>/jobs --paginate > /tmp/jobs.json
npx tsx scripts/ci-timing-summary.ts --input /tmp/jobs.json --json /tmp/ci-timing-summary.json --markdown /tmp/ci-timing-summary.md| Benchmark | Time |
|---|---|
| Simple HTML (100 elements) | ~27 µs |
| Large document (100 sections × 20 paragraphs) | ~5.2 ms |
| Attribute-heavy (200 elements, 6 attrs each) | ~390 µs |
| Table (100×20 cells) | ~990 µs |
moon bench -p htmlmoon add mizchi/cratermoon add mizchi/crater-layout
moon add mizchi/crater-css
moon add mizchi/crater-dom
moon add mizchi/crater-renderer
moon add mizchi/crater-browser
moon add mizchi/crater-browser-runtime
moon add mizchi/crater-webdriver-bidi
moon add mizchi/crater-wasm// Parse HTML and render layout
///|
let html = "<div style=\"display: flex; width: 300px;\"><div style=\"flex: 1\">A</div><div style=\"flex: 2\">B</div></div>"
///|
let ctx = @renderer.RenderContext::default()
///|
let layout = @renderer.render(html, ctx)
// layout contains x, y, width, height for each elementfn compute_element_shift(before : BoundingRect, after : BoundingRect, viewport : Size[Double]) -> LayoutShiftfn compute_total_cls(before : Array[BoundingRect], after : Array[BoundingRect], viewport : Size[Double]) -> Doublefn diff_rendered_paint_trees(baseline_html : String, current_html : String, viewport : Size[Double]) -> PaintTreeDifffn render_html_batch_variants(html : String, viewport : Size[Double], variants : Array[RenderVariant]) -> Array[RenderVariantResult]