HS: closest parent <sel> traversal (+1 test)
parse-trav recognises `parent` as an ident modifier after the `closest` keyword — consumes it and re-invokes with kind `closest-parent`, producing AST `(closest-parent "div" (me))` instead of the generic trailing-ident-as-unit shape `(string-postfix (closest "*" (me)) "parent")`. Compiler translates `(closest-parent sel target)` to `(dom-closest (host-get target "parentElement") sel)` so `me` is skipped and only strict ancestors match. `closest-parent` also joined the `put X into <trav>` inner-html shortcut alongside next/previous/closest. Suite hs-upstream-core/regressions: 10/16 → 11/16. Smoke 0-195: 162/195 → 163/195.
This commit is contained in:
@@ -109,7 +109,7 @@
|
|||||||
(hs-to-sx (nth target 1))
|
(hs-to-sx (nth target 1))
|
||||||
(hs-to-sx (nth target 2))
|
(hs-to-sx (nth target 2))
|
||||||
value))
|
value))
|
||||||
((or (= th (quote next)) (= th (quote previous)) (= th (quote closest)))
|
((or (= th (quote next)) (= th (quote previous)) (= th (quote closest)) (= th (quote closest-parent)))
|
||||||
(list (quote hs-set-inner-html!) (hs-to-sx target) value))
|
(list (quote hs-set-inner-html!) (hs-to-sx target) value))
|
||||||
((= th (quote of))
|
((= th (quote of))
|
||||||
(let
|
(let
|
||||||
@@ -966,7 +966,11 @@
|
|||||||
((= prop "first") (list (quote hs-first) target))
|
((= prop "first") (list (quote hs-first) target))
|
||||||
((= prop "last") (list (quote hs-last) target))
|
((= prop "last") (list (quote hs-last) target))
|
||||||
(true (list (quote host-get) target prop)))))
|
(true (list (quote host-get) target prop)))))
|
||||||
((= head (quote ref)) (if (= (nth ast 1) "selection") (list (quote hs-get-selection)) (make-symbol (nth ast 1))))
|
((= head (quote ref))
|
||||||
|
(if
|
||||||
|
(= (nth ast 1) "selection")
|
||||||
|
(list (quote hs-get-selection))
|
||||||
|
(make-symbol (nth ast 1))))
|
||||||
((= head (quote query))
|
((= head (quote query))
|
||||||
(list (quote hs-query-first) (nth ast 1)))
|
(list (quote hs-query-first) (nth ast 1)))
|
||||||
((= head (quote query-scoped))
|
((= head (quote query-scoped))
|
||||||
@@ -1153,6 +1157,14 @@
|
|||||||
(quote dom-closest)
|
(quote dom-closest)
|
||||||
(hs-to-sx (nth ast 2))
|
(hs-to-sx (nth ast 2))
|
||||||
(nth ast 1)))
|
(nth ast 1)))
|
||||||
|
((= head (quote closest-parent))
|
||||||
|
(list
|
||||||
|
(quote dom-closest)
|
||||||
|
(list
|
||||||
|
(quote host-get)
|
||||||
|
(hs-to-sx (nth ast 2))
|
||||||
|
"parentElement")
|
||||||
|
(nth ast 1)))
|
||||||
((= head (quote next))
|
((= head (quote next))
|
||||||
(list (quote hs-next) (hs-to-sx (nth ast 2)) (nth ast 1)))
|
(list (quote hs-next) (hs-to-sx (nth ast 2)) (nth ast 1)))
|
||||||
((= head (quote previous))
|
((= head (quote previous))
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
(let
|
(let
|
||||||
((typ (tp-type)) (val (tp-val)))
|
((typ (tp-type)) (val (tp-val)))
|
||||||
(cond
|
(cond
|
||||||
|
((and (= kind (quote closest)) (= typ "ident") (= val "parent"))
|
||||||
|
(do (adv!) (parse-trav (quote closest-parent))))
|
||||||
((= typ "selector")
|
((= typ "selector")
|
||||||
(do (adv!) (list kind val (list (quote me)))))
|
(do (adv!) (list kind val (list (quote me)))))
|
||||||
((= typ "class")
|
((= typ "class")
|
||||||
@@ -2507,8 +2509,13 @@
|
|||||||
((acc2 (append acc (list cmd))))
|
((acc2 (append acc (list cmd))))
|
||||||
(cond
|
(cond
|
||||||
((match-kw "unless")
|
((match-kw "unless")
|
||||||
(let ((cnd (parse-expr)))
|
(let
|
||||||
(cl-collect (append acc (list (list (quote if) (list (quote no) cnd) cmd))))))
|
((cnd (parse-expr)))
|
||||||
|
(cl-collect
|
||||||
|
(append
|
||||||
|
acc
|
||||||
|
(list
|
||||||
|
(list (quote if) (list (quote no) cnd) cmd))))))
|
||||||
((match-kw "then")
|
((match-kw "then")
|
||||||
(cl-collect (append acc2 (list (quote __then__)))))
|
(cl-collect (append acc2 (list (quote __then__)))))
|
||||||
((and (not (at-end?)) (= (tp-type) "keyword") (cmd-kw? (tp-val)))
|
((and (not (at-end?)) (= (tp-type) "keyword") (cmd-kw? (tp-val)))
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ Live tally for `plans/hs-conformance-to-100.md`. Update after every cluster comm
|
|||||||
|
|
||||||
```
|
```
|
||||||
Baseline: 1213/1496 (81.1%)
|
Baseline: 1213/1496 (81.1%)
|
||||||
Merged: 1247/1496 (83.4%) delta +34
|
Merged: 1248/1496 (83.4%) delta +35
|
||||||
Worktree: all merged
|
Worktree: all merged
|
||||||
Target: 1496/1496 (100.0%)
|
Target: 1496/1496 (100.0%)
|
||||||
Remaining: ~249 tests
|
Remaining: ~248 tests
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cluster ledger
|
## Cluster ledger
|
||||||
@@ -43,7 +43,7 @@ Remaining: ~249 tests
|
|||||||
| 20 | `repeat` property for-loops + where | pending | (+3 est) | — |
|
| 20 | `repeat` property for-loops + where | pending | (+3 est) | — |
|
||||||
| 21 | `possessiveExpression` property access via its | done | +1 | f0c41278 |
|
| 21 | `possessiveExpression` property access via its | done | +1 | f0c41278 |
|
||||||
| 22 | window global fn fallback | blocked | — | — |
|
| 22 | window global fn fallback | blocked | — | — |
|
||||||
| 23 | `me symbol works in from expressions` | pending | (+1 est) | — |
|
| 23 | `me symbol works in from expressions` | done | +1 | (pending) |
|
||||||
| 24 | `properly interpolates values 2` | pending | (+1 est) | — |
|
| 24 | `properly interpolates values 2` | pending | (+1 est) | — |
|
||||||
| 25 | parenthesized commands and features | pending | (+1 est) | — |
|
| 25 | parenthesized commands and features | pending | (+1 est) | — |
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ Defer until A–D drain. Estimated ~25 recoverable tests.
|
|||||||
| Bucket | Done | Partial | In-prog | Pending | Blocked | Design-done | Total |
|
| Bucket | Done | Partial | In-prog | Pending | Blocked | Design-done | Total |
|
||||||
|--------|-----:|--------:|--------:|--------:|--------:|------------:|------:|
|
|--------|-----:|--------:|--------:|--------:|--------:|------------:|------:|
|
||||||
| A | 12 | 4 | 0 | 0 | 1 | — | 17 |
|
| A | 12 | 4 | 0 | 0 | 1 | — | 17 |
|
||||||
| B | 1 | 0 | 0 | 5 | 1 | — | 7 |
|
| B | 2 | 0 | 0 | 4 | 1 | — | 7 |
|
||||||
| C | 0 | 0 | 0 | 5 | 0 | — | 5 |
|
| C | 0 | 0 | 0 | 5 | 0 | — | 5 |
|
||||||
| D | 0 | 0 | 0 | 5 | 0 | — | 5 |
|
| D | 0 | 0 | 0 | 5 | 0 | — | 5 |
|
||||||
| E | 0 | 0 | 0 | 0 | 0 | 5 | 5 |
|
| E | 0 | 0 | 0 | 0 | 0 | 5 | 5 |
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ Each cluster below is one commit. Order is rough — a loop agent may skip ahead
|
|||||||
|
|
||||||
22. **[blocked: tried three compile-time emits — (1) guard (can't catch Undefined symbol since it's a host-level error, not an SX raise), (2) env-has? (primitive not loaded in HS kernel — `Unhandled exception: "env-has?"`), and (3) hs-win-call runtime helper (works when reached but SX can't CALL a host-handle function directly — `Not callable: {:__host_handle N}` because NativeFn is not callable here). Needs either a host-call-fn primitive with arity-agnostic dispatch OR a symbol-bound? predicate in the HS kernel.] window global fn fallback** — `regressions / can invoke functions w/ numbers in name` + unlocks several others. When calling `foo()` where `foo` isn't SX-defined, fall back to `(host-global "foo")`. Design decision: either compile-time emit `(or foo (host-global "foo"))` via a helper, or add runtime lookup in the dispatch path. Expected: +2-4.
|
22. **[blocked: tried three compile-time emits — (1) guard (can't catch Undefined symbol since it's a host-level error, not an SX raise), (2) env-has? (primitive not loaded in HS kernel — `Unhandled exception: "env-has?"`), and (3) hs-win-call runtime helper (works when reached but SX can't CALL a host-handle function directly — `Not callable: {:__host_handle N}` because NativeFn is not callable here). Needs either a host-call-fn primitive with arity-agnostic dispatch OR a symbol-bound? predicate in the HS kernel.] window global fn fallback** — `regressions / can invoke functions w/ numbers in name` + unlocks several others. When calling `foo()` where `foo` isn't SX-defined, fall back to `(host-global "foo")`. Design decision: either compile-time emit `(or foo (host-global "foo"))` via a helper, or add runtime lookup in the dispatch path. Expected: +2-4.
|
||||||
|
|
||||||
23. **[pending] `me symbol works in from expressions`** — `regressions` (1 test, Expected `Foo`). Check `from` expression compilation. Expected: +1.
|
23. **[done (+1)] `me symbol works in from expressions`** — `regressions` (1 test, Expected `Foo`). Check `from` expression compilation. Expected: +1.
|
||||||
|
|
||||||
24. **[pending] `properly interpolates values 2`** — URL interpolation regression (1 test). Likely template string + property access. Expected: +1.
|
24. **[pending] `properly interpolates values 2`** — URL interpolation regression (1 test). Likely template string + property access. Expected: +1.
|
||||||
|
|
||||||
@@ -162,6 +162,9 @@ Many tests are `SKIP (untranslated)` because `tests/playwright/generate-sx-tests
|
|||||||
|
|
||||||
(Reverse chronological — newest at top.)
|
(Reverse chronological — newest at top.)
|
||||||
|
|
||||||
|
### 2026-04-24 — cluster 23 me symbol works in from expressions
|
||||||
|
- **COMMIT** — `HS: closest parent <sel> traversal (+1 test)`. `parse-trav` now recognises `parent` as an ident modifier after the `closest` keyword: consumes it and re-invokes itself with kind `closest-parent`, so `closest parent <div/>` produces AST `(closest-parent "div" (me))` instead of `(string-postfix (closest "*" (me)) "parent")` — the latter was the generic trailing-ident-as-unit rule swallowing `parent`. Compiler translates `(closest-parent sel target)` to `(dom-closest (host-get target "parentElement") sel)` so `me` (the element with the `_` attribute) is skipped and only strict ancestors match. Also added `closest-parent` to the `put X into <trav>` inner-html shortcut alongside `next`/`previous`/`closest`. Suite hs-upstream-core/regressions: 10/16 → 11/16. Smoke 0-195: 162/195 → 163/195.
|
||||||
|
|
||||||
### 2026-04-24 — cluster 8 select returns selected text (cherry-picked from worktree)
|
### 2026-04-24 — cluster 8 select returns selected text (cherry-picked from worktree)
|
||||||
- **0b9bbc7b** — `HS: select returns selected text (+1 test)`. Runtime `hs-get-selection` prefers `window.__test_selection` stash and falls back to `getSelection().toString()`. Compiler rewrites `(ref "selection")` to `(hs-get-selection)`. Generator detects `document.createRange() + getElementById(ID).firstChild + setStart/setEnd` and emits a single `host-set!` on `window.__test_selection` with the resolved substring, sidestepping a propagating DOM range/text-node mock. Runner resets `__test_selection` between tests. Suite hs-upstream-select: 3/4 → 4/4.
|
- **0b9bbc7b** — `HS: select returns selected text (+1 test)`. Runtime `hs-get-selection` prefers `window.__test_selection` stash and falls back to `getSelection().toString()`. Compiler rewrites `(ref "selection")` to `(hs-get-selection)`. Generator detects `document.createRange() + getElementById(ID).firstChild + setStart/setEnd` and emits a single `host-set!` on `window.__test_selection` with the resolved substring, sidestepping a propagating DOM range/text-node mock. Runner resets `__test_selection` between tests. Suite hs-upstream-select: 3/4 → 4/4.
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@
|
|||||||
(hs-to-sx (nth target 1))
|
(hs-to-sx (nth target 1))
|
||||||
(hs-to-sx (nth target 2))
|
(hs-to-sx (nth target 2))
|
||||||
value))
|
value))
|
||||||
((or (= th (quote next)) (= th (quote previous)) (= th (quote closest)))
|
((or (= th (quote next)) (= th (quote previous)) (= th (quote closest)) (= th (quote closest-parent)))
|
||||||
(list (quote hs-set-inner-html!) (hs-to-sx target) value))
|
(list (quote hs-set-inner-html!) (hs-to-sx target) value))
|
||||||
((= th (quote of))
|
((= th (quote of))
|
||||||
(let
|
(let
|
||||||
@@ -966,7 +966,11 @@
|
|||||||
((= prop "first") (list (quote hs-first) target))
|
((= prop "first") (list (quote hs-first) target))
|
||||||
((= prop "last") (list (quote hs-last) target))
|
((= prop "last") (list (quote hs-last) target))
|
||||||
(true (list (quote host-get) target prop)))))
|
(true (list (quote host-get) target prop)))))
|
||||||
((= head (quote ref)) (if (= (nth ast 1) "selection") (list (quote hs-get-selection)) (make-symbol (nth ast 1))))
|
((= head (quote ref))
|
||||||
|
(if
|
||||||
|
(= (nth ast 1) "selection")
|
||||||
|
(list (quote hs-get-selection))
|
||||||
|
(make-symbol (nth ast 1))))
|
||||||
((= head (quote query))
|
((= head (quote query))
|
||||||
(list (quote hs-query-first) (nth ast 1)))
|
(list (quote hs-query-first) (nth ast 1)))
|
||||||
((= head (quote query-scoped))
|
((= head (quote query-scoped))
|
||||||
@@ -1153,6 +1157,14 @@
|
|||||||
(quote dom-closest)
|
(quote dom-closest)
|
||||||
(hs-to-sx (nth ast 2))
|
(hs-to-sx (nth ast 2))
|
||||||
(nth ast 1)))
|
(nth ast 1)))
|
||||||
|
((= head (quote closest-parent))
|
||||||
|
(list
|
||||||
|
(quote dom-closest)
|
||||||
|
(list
|
||||||
|
(quote host-get)
|
||||||
|
(hs-to-sx (nth ast 2))
|
||||||
|
"parentElement")
|
||||||
|
(nth ast 1)))
|
||||||
((= head (quote next))
|
((= head (quote next))
|
||||||
(list (quote hs-next) (hs-to-sx (nth ast 2)) (nth ast 1)))
|
(list (quote hs-next) (hs-to-sx (nth ast 2)) (nth ast 1)))
|
||||||
((= head (quote previous))
|
((= head (quote previous))
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
(let
|
(let
|
||||||
((typ (tp-type)) (val (tp-val)))
|
((typ (tp-type)) (val (tp-val)))
|
||||||
(cond
|
(cond
|
||||||
|
((and (= kind (quote closest)) (= typ "ident") (= val "parent"))
|
||||||
|
(do (adv!) (parse-trav (quote closest-parent))))
|
||||||
((= typ "selector")
|
((= typ "selector")
|
||||||
(do (adv!) (list kind val (list (quote me)))))
|
(do (adv!) (list kind val (list (quote me)))))
|
||||||
((= typ "class")
|
((= typ "class")
|
||||||
@@ -2507,8 +2509,13 @@
|
|||||||
((acc2 (append acc (list cmd))))
|
((acc2 (append acc (list cmd))))
|
||||||
(cond
|
(cond
|
||||||
((match-kw "unless")
|
((match-kw "unless")
|
||||||
(let ((cnd (parse-expr)))
|
(let
|
||||||
(cl-collect (append acc (list (list (quote if) (list (quote no) cnd) cmd))))))
|
((cnd (parse-expr)))
|
||||||
|
(cl-collect
|
||||||
|
(append
|
||||||
|
acc
|
||||||
|
(list
|
||||||
|
(list (quote if) (list (quote no) cnd) cmd))))))
|
||||||
((match-kw "then")
|
((match-kw "then")
|
||||||
(cl-collect (append acc2 (list (quote __then__)))))
|
(cl-collect (append acc2 (list (quote __then__)))))
|
||||||
((and (not (at-end?)) (= (tp-type) "keyword") (cmd-kw? (tp-val)))
|
((and (not (at-end?)) (= (tp-type) "keyword") (cmd-kw? (tp-val)))
|
||||||
|
|||||||
Reference in New Issue
Block a user