Preserve supported runtime rules when the browser rejects CSSOM nodes
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- css, typescript
- Lĩnh vực
- frontend, performance, testing
Hướng nghiên cứu
Start with packages/runtime/src/layer.ts, host.ts, and core.ts, then reproduce the mixed manifest case in Chromium or WebKit. Read the existing correctness-regressions.test.ts case named “hydration rejects CSSOM nodes dropped by the browser” and add focused coverage for rejected nodes around supported rules. Done means supported 21px styling survives rendering, hydration, insertion, deletion, refresh, and fallback while mismatch checks remain strict.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem and classification
P1 · Required for the 2.0 freeze. A browser-rejected selector can prevent a later, supported rule from being inserted. Progressive hydration can consequently remove styling that was already working in the server-rendered page.
Parent: #445. Implementation detail of the rendering-equivalence work in #451; completion evidence feeds #454. This issue adds a newly reproduced counterexample, not another general rendering audit.
Baseline: 70444b18c8102fa7a9d811ec51ef96902573792c. Reproduced locally on 2026-09-27 in Chromium and WebKit. The new counterexample has not been run in Firefox. Concurrent local freeze documentation/tests are unrelated and must be preserved.
Reproduction and observed behavior
Use this public execution manifest with an element whose class is mixed:
const manifest = {
version: 1,
languageVersion: 3,
utilities: [{
id: 'mixed',
name: 'mixed',
type: 0,
matchers: [{ type: 'static', name: 'mixed' }],
emit: {
type: 'static',
rules: [
{ selector: '&:mastercss-unknown-pseudo', declarations: { color: 'red' } },
{ declarations: { width: '21px' } }
]
}
}]
}
const runtime = await MasterCSSRuntime.start({ manifest })
runtime.observe()
The engine correctly preserves both rules:
@layer utilities {
.mixed:mastercss-unknown-pseudo { color: red }
.mixed { width: 21px }
}
| Path | Observed result in both tested browsers |
|---|---|
| Load generated CSS directly | The browser drops the unknown-selector rule; width is 21px. |
| Generate through runtime | The first insertion throws SyntaxError; the second throws IndexSizeError; the layer is empty. |
| Hydrate the working SSR output | Width changes from 21px to automatic width (1264px in the probe viewport). The engine snapshot still contains both rules. |
The existing correctness-regressions.test.ts case named “hydration rejects CSSOM nodes dropped by the browser” does not exercise a rejected node preceding a supported node in this multi-node output.
Cause and source evidence
- layer.ts increments offsets and node counts before insertion, using expected output node counts.
- host.ts continues with
nativeIndex + nodeIndexafter a failed insertion; deletion also assumes all expected nodes exist. - core.ts requires browser node counts to equal engine node counts during hydration.
CSSOM permits parsing to fail and requires an index beyond the current rule count to fail separately.
Implementation plan
- Keep Rust rules, ordering, resource ownership and generated CSS unchanged. Do not restore host-support filtering or add a runtime CSS grammar validator.
- Separate logical rule/node identity from successful CSSOM attachment. Each generated node may have zero or one attached top-level CSSOM node; a logical rule can have multiple generated nodes. Compute insertion/deletion offsets from actual attachments.
- Make insertion failures local to the rejected node. Preserve supported siblings and subsequent rules in Rust order. Distinguish browser parsing rejection from internal index/bookkeeping errors; do not label every exception as unsupported CSS.
- Delete only nodes actually owned by the removed rule. A rejected node must never consume an adjacent rule's deletion slot.
- Build the same attachment mapping for fresh rendering, snapshot adoption, refresh, hydration and fallback. Match the browser-parsed projection while retaining strict checks for changed, extra, missing, duplicated or reordered supported rules/resources. Removing the node-count assertion alone is insufficient.
- Preserve complete engine snapshots and resource accounting. Browser omission must not change semantic output or masquerade as successful physical insertion.
- Add permanent focused regressions and document the distinction between generated CSS and browser-attached CSS. This is a runtime correctness fix, not a class-language change.
Acceptance and validation
- Rejected nodes before, between and after supported nodes work within one multi-node rule and across separate rules.
- Insert/delete/reinsert, shared classes, refresh, retention cleanup and last-reference removal preserve unrelated styles and resources.
- Static, SSR, runtime and progressive paths retain the supported
21pxdeclaration. Hydration and later DOM changes do not introduce style loss. - Cover unknown selectors and browser-dropped contents inside wrappers, supported siblings, all utility layers, Document and ShadowRoot.
- Existing hydration tampering tests continue to reject actual mismatches.
- Run focused and then affected runtime e2e in Chromium, WebKit and Firefox; report unrun/environment-blocked cases honestly. Run runtime lint, type-check and build, and relevant server/hydration tests.
- Measure runtime insertion/deletion/hydration hot paths and complete runtime JS/Wasm/manifest payload against the same baseline/workload. Remeasure regressions above 5% and explain the cost; do not recover speed by weakening matching.
Boundaries and integration
No new syntax, Manifest/hydration wire shape, browser-support database, compiler fallback or release/CI changes are intended. The nonce/atomic-delivery follow-up #463 shares hydration code; land this mapping work first, then integrate #463 and run their combined matrix once. Add results to #451 and #454 rather than duplicating their broader audits. Preserve the ongoing #445 worktree changes.
- Ngôn ngữ chính
- TypeScript
- Star
- 2k
- Fork
- 44
- Merge trung bình
- 1 ngày 3 giờ
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của master-co/css
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
breaking change runtime
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
-
runtime server
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 28/100
Tất cả issue của master-co/css
Issue tương tự
-
afk-ok area:data-quality importer size:S
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
enorm-labs/event-junkie#3301 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
one-zero-eight/apply-bot#39 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
bigbluebutton/bbb-ui-components-react#108 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
area: app type: bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
ExpidetGames/code-reviewer#308 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày