#11-tags-T2d-input-list: implement <input>.list IDREF → <datalist> resolution (HTML §4.10.5.1.16)#195
Merged
Merged
Conversation
…solution (HTML §4.10.5.1.16) Closes the §H-7k T2d defer slot. The previous stub returned `null` unconditionally because the T2d datalist surface was not yet shipped; PR #181 landed `<datalist>` infrastructure, so the IDREF back-ref is now implementable. Engine-indep resolver `resolve_input_list` lives in `elidex-form/src/input.rs` sibling to `resolve_label_for` (HTML §4.10.4) — same shape: read attr, walk input's tree root-inclusive, filter-during-walk for first matching datalist. VM-side getter is pure marshalling: brand check via `require_input_receiver`, call resolver, wrap via `wrap_entity_or_null`. - Tree scope honors shadow boundaries — nested shadow subtrees within the same root are excluded per spec "same tree" wording. Cross-tree resolution tracked at `#11-form-elements-cross-tree`. - Tag match ASCII-CI (HTML §3.2.6.5); id match case-sensitive (§6.13.2). - Filter-during-walk: a `<div id="x">` appearing earlier in tree order before `<datalist id="x">` does NOT poison the lookup (spec: "first element of type HTMLDataListElement"). - Identity-stable across reads via `create_element_wrapper`'s per-entity cache — HTML §4.10.5.1.16 IDL is not `[SameObject]` but matches Chrome / Firefox behaviour. - HTML-namespace filter currently omitted because `TagType` implies element-hood in elidex's HTML-only model; defer slot `#11-element-namespace-tracking` tracks the tightening. - 12 engine-indep tests + 6 VM tests cover spec edge cases (no-attr / empty / id-not-exist / target-not-datalist / matched / duplicate-id tree-order / case-sensitive / non-datalist-then-datalist / detached / self-ref / no-whitespace-trim / empty-id-skip-then-match / identity). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements <input>.list datalist resolution by adding an engine-independent IDREF lookup helper and wiring the VM accessor to return the matched <datalist> wrapper instead of the previous null stub.
Changes:
- Added
elidex_form::resolve_input_listand re-exported it. - Updated
HTMLInputElement.prototype.listto resolve and wrap matching datalist elements. - Expanded engine-independent and VM-level tests for list resolution behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
crates/dom/elidex-form/src/input.rs |
Adds the <input>.list resolution algorithm and unit tests. |
crates/dom/elidex-form/src/lib.rs |
Re-exports resolve_input_list. |
crates/script/elidex-js/src/vm/host/html_input_proto.rs |
Wires the list getter to the new form helper. |
crates/script/elidex-js/src/vm/tests/tests_html_input_proto.rs |
Replaces the null-stub test with VM tests for datalist resolution. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… input type applicability (HTML §4.10.5.1.16) Per WHATWG HTML §4.10.5.1.16: the `list` IDL attribute does not apply to input types `hidden` / `checkbox` / `radio` / `file` / `submit` / `image` / `reset` / `button` / `password`. The getter must return null for these types even when a matching `<datalist>` exists in the same tree. - Add `FormControlKind::list_applies()` predicate (sibling to `readonly_applies` shape) listing the allow-listed kinds. - Add `input_list_applies_to_type(dom, entity)` helper with the `FormControlState.kind` → raw `type` attribute fallback pattern from `label.rs::is_labelable_element`. - Gate `resolve_input_list` on it (early null before any IDREF walk). - 9 new engine-indep regression tests covering each excluded type plus the FormControlState-path and ASCII-CI attr-path coverage. - 1 new VM test looping over all 8 excluded types. Image type is documented as a pre-existing FormControlKind coverage gap (falls back to TextInput via `from_type_str`) — out of scope here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
crates/dom/elidex-form/src/input.rs:755
- This added test block pushes
crates/dom/elidex-form/src/input.rspast the repository's documented ~1000-line convention for splitting large Rust modules/tests (for example,crates/dom/elidex-dom-api/src/element/mod.rs:35-36). Please split the newresolve_input_listtests into a sibling test module/file to keep this module within the established size limit.
// -----------------------------------------------------------------
// resolve_input_list — HTML §4.10.5.1.16 `<input>.list` IDREF
// -----------------------------------------------------------------
…applicability check, includes image type (HTML §4.10.5.1.16)
Three R2 findings, single root cause: `input_list_applies_to_type`
preferred the cached `FormControlState.kind` over the live `type`
content attribute, and routed the exclusion check through
`FormControlKind::from_type_str` which collapses `"image"` onto
`TextInput`. Two interlocking bugs:
1. `setAttribute('type', 'hidden')` (or `image` / `checkbox` / ...) only
mutates `Attributes`; `state.kind` lags until a type-change sync
pass. Preferring the cached kind let stale state mask the mutation
and incorrectly resolve a datalist.
2. `<input type=image>` falls back to `TextInput` via `from_type_str`,
which was on the allow-list — wrongly admitting image.
Fix: rewrite `input_list_applies_to_type` to read the `type` content
attribute directly (spec source of truth per HTML §4.10.5.1.16) and
match against the literal exclusion set { hidden, checkbox, radio,
file, submit, image, reset, button, password }. Dropped the orphan
`FormControlKind::list_applies` predicate (its sole caller was the
removed code path; the from_type_str/image gap made it
unmaintainable as a public predicate).
- Stale-state regression test
(`resolve_input_list_ignores_stale_form_control_state_when_attr_excludes`)
attaches a `TextInput`-kind state to an `<input type=hidden>` and
asserts the attribute wins.
- Dedicated `resolve_input_list_returns_none_for_image_type` test.
- `image` added to the existing button-types loop + the VM
inapplicable-types loop.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… to sibling input_tests.rs (1000-line convention) R3 finding: `input.rs` reached 1075 LoC, violating the project's ~1000-line file convention documented in `cleanup-1000-line-files-tranche-3-complete.md`. Move the entire `#[cfg(test)] mod tests` body to a new sibling file `input_tests.rs` and include it via the established `#[cfg(test)] #[path = "input_tests.rs"] mod tests;` pattern (mirror of `lib.rs:743` precedent). Post-split: `input.rs` is 404 LoC (production-only), `input_tests.rs` is 671 LoC (test-only). Test count and contents unchanged — 55 tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this PR
Closes the §H-7k T2d defer slot
#11-tags-T2d-input-list(~50 LoC stub since PR #181 D-7 T2d). The original trigger ("T2d datalist surface lands → user / WPT report") has fired: PR #181 shipped<datalist>ctor + per-tag prototype +datalist.optionsHTMLCollection, so the IDREF back-ref from<input>.listis now implementable.Per
feedback_ship-first-over-close: ship-close rather than close-as-won't-fix.Scope
Engine-indep (
crates/dom/elidex-form/)input.rs::resolve_input_list(dom, input_entity)— sibling toresolve_label_for(HTML §4.10.4), same shape:listcontent attributeNonefind_tree_root→ root-inclusive pre-order DFS viatraverse_descendants<datalist>(ASCII-CI tag) with matchingid(case-sensitive per §6.13.2)matches_datalist_with_idhelper — tag-first guard cascadelib.rsre-export addedVM thin binding (
crates/script/elidex-js/src/vm/host/)html_input_proto.rs::native_input_get_list— replacedOk(JsValue::Null)stub with:require_input_receiver(brand check first) →elidex_form::resolve_input_list→wrap_entity_or_null. Mirrorsnative_input_get_form(find_form_ancestor) call shape.tests_html_input_proto.rs— deletedinput_list_returns_null_stub, added 6 VM tests including identity-stable-across-reads regressionBoa parallel
input.liststub; deletion path permemory/project_boa_runtime_deletion.md)Spec compliance
WHATWG HTML §4.10.5.1.16: "the first element in the tree of type
HTMLDataListElementwhose ID is equal to the value of thelistattribute, if that element is in the same tree as the input element"<div id="x">before<datalist id="x">)find_tree_root; honors shadow boundaries)create_element_wrapperper-entity cache; not[SameObject]in IDL but matches Chrome/Firefox)Out of scope (documented)
#11-form-elements-cross-treeTagTypeimplies element-hood in elidex's HTML-only model; tracked at#11-element-namespace-tracking(forward-reference comment inmatches_datalist_with_id)Defer ledger impact
Pre-PR: 36/35 over-cap-by-1.
Closes:
#11-tags-T2d-input-list(§H-7k row).Opens: 0 NEW.
Post-PR: 35/35 cap-at, headroom 0.
Test plan
cargo fmt --allmise run ci— all greencargo test -p elidex-form --all-features --lib input::tests::resolve_input_list— 12 passcargo test -p elidex-js --all-features --lib tests_html_input_proto::input_list— 6 pass/simplifypre-push — 1 efficiency fix (drop tautologicalis_html_namespace) + 2 doc trims/reviewpre-push — TERMINAL (0 CRIT, 0 IMP, 4 MIN optional, 0 FP)🤖 Generated with Claude Code