HS-gen: string-aware line-comment stripping (+1 test)
process_hs_val stripped `//…` line comments with a naïve regex, which devoured `https://yyy.xxxxxx.com/…` inside a backtick template — the 'properly interpolates values 2' fixture was landing with the HS source truncated at `https:`. New helper _strip_hs_line_comments walks char-by-char and only strips `//` / leading-whitespace `--` when not inside `'…'`, `"…"`, or backticks; respects `\\`-escapes inside strings. Suite hs-upstream-core/regressions: 11/16 → 12/16. Smoke 0-195: 163/195 → 164/195.
This commit is contained in:
@@ -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: 1248/1496 (83.4%) delta +35
|
Merged: 1249/1496 (83.5%) delta +36
|
||||||
Worktree: all merged
|
Worktree: all merged
|
||||||
Target: 1496/1496 (100.0%)
|
Target: 1496/1496 (100.0%)
|
||||||
Remaining: ~248 tests
|
Remaining: ~247 tests
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cluster ledger
|
## Cluster ledger
|
||||||
@@ -44,7 +44,7 @@ Remaining: ~248 tests
|
|||||||
| 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` | done | +1 | 0d38a75b |
|
| 23 | `me symbol works in from expressions` | done | +1 | 0d38a75b |
|
||||||
| 24 | `properly interpolates values 2` | pending | (+1 est) | — |
|
| 24 | `properly interpolates values 2` | done | +1 | (pending) |
|
||||||
| 25 | parenthesized commands and features | pending | (+1 est) | — |
|
| 25 | parenthesized commands and features | pending | (+1 est) | — |
|
||||||
|
|
||||||
### Bucket C — feature stubs (observer mocks)
|
### Bucket C — feature stubs (observer mocks)
|
||||||
@@ -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 | 2 | 0 | 0 | 4 | 1 | — | 7 |
|
| B | 3 | 0 | 0 | 3 | 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 |
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Each cluster below is one commit. Order is rough — a loop agent may skip ahead
|
|||||||
|
|
||||||
23. **[done (+1)] `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. **[done (+1)] `properly interpolates values 2`** — URL interpolation regression (1 test). Likely template string + property access. Expected: +1.
|
||||||
|
|
||||||
25. **[pending] `can support parenthesized commands and features`** — `parser` (1 test, Expected `clicked`). Parser needs to accept `(cmd...)` grouping in more contexts. Expected: +1.
|
25. **[pending] `can support parenthesized commands and features`** — `parser` (1 test, Expected `clicked`). Parser needs to accept `(cmd...)` grouping in more contexts. 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 24 properly interpolates values 2
|
||||||
|
- **COMMIT** — `HS-gen: string-aware line-comment stripping (+1 test)`. `process_hs_val` in `tests/playwright/generate-sx-tests.py` stripped `//…` line comments with a naïve regex, which devoured `https://yyy.xxxxxx.com/…` inside a backtick template — test 2074 was landing with the HS source truncated at `https:`. New helper `_strip_hs_line_comments` walks char-by-char and only strips `//` / leading-whitespace `--` when not inside `'…'`, `"…"`, or `` `…` ``; also respects `\\`-escapes inside strings. Regen produced full template intact. Suite hs-upstream-core/regressions: 11/16 → 12/16. Smoke 0-195: 163/195 → 164/195.
|
||||||
|
|
||||||
### 2026-04-24 — cluster 23 me symbol works in from expressions
|
### 2026-04-24 — cluster 23 me symbol works in from expressions
|
||||||
- **0d38a75b** — `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.
|
- **0d38a75b** — `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.
|
||||||
|
|
||||||
|
|||||||
@@ -2070,7 +2070,7 @@
|
|||||||
(deftest "properly interpolates values 2"
|
(deftest "properly interpolates values 2"
|
||||||
(hs-cleanup!)
|
(hs-cleanup!)
|
||||||
(let ((_el-button (dom-create-element "button")))
|
(let ((_el-button (dom-create-element "button")))
|
||||||
(dom-set-attr _el-button "_" "on click set trackingcode to `AB123456789KK` then set pdfurl to `https:")
|
(dom-set-attr _el-button "_" "on click set trackingcode to `AB123456789KK` then set pdfurl to `https://yyy.xxxxxx.com/path/out/${trackingcode}.pdf` then put pdfurl into me")
|
||||||
(dom-append (dom-body) _el-button)
|
(dom-append (dom-body) _el-button)
|
||||||
(hs-activate! _el-button)
|
(hs-activate! _el-button)
|
||||||
(dom-dispatch _el-button "click" nil)
|
(dom-dispatch _el-button "click" nil)
|
||||||
@@ -11019,7 +11019,7 @@
|
|||||||
(deftest "handles set url regression properly"
|
(deftest "handles set url regression properly"
|
||||||
(hs-cleanup!)
|
(hs-cleanup!)
|
||||||
(let ((_el-div (dom-create-element "div")))
|
(let ((_el-div (dom-create-element "div")))
|
||||||
(dom-set-attr _el-div "_" "on click set trackingcode to `foo` then set pdfurl to `https:")
|
(dom-set-attr _el-div "_" "on click set trackingcode to `foo` then set pdfurl to `https://yyy.xxxxxx.com/path/out/${trackingcode}.pdf` then put pdfurl into me")
|
||||||
(dom-set-inner-html _el-div "lolwat")
|
(dom-set-inner-html _el-div "lolwat")
|
||||||
(dom-append (dom-body) _el-div)
|
(dom-append (dom-body) _el-div)
|
||||||
(hs-activate! _el-div)
|
(hs-activate! _el-div)
|
||||||
|
|||||||
@@ -1177,6 +1177,45 @@ def parse_dev_body(body, elements, var_names):
|
|||||||
|
|
||||||
# ── Test generation ───────────────────────────────────────────────
|
# ── Test generation ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
def _strip_hs_line_comments(s):
|
||||||
|
"""Strip `//…` and `--…` line comments outside HS string literals.
|
||||||
|
|
||||||
|
HS has three string delimiters: single quotes, double quotes, and
|
||||||
|
backticks (template strings). `https://…` inside a backtick must not
|
||||||
|
be treated as a comment.
|
||||||
|
"""
|
||||||
|
out = []
|
||||||
|
i = 0
|
||||||
|
n = len(s)
|
||||||
|
in_str = None # None | "'" | '"' | '`'
|
||||||
|
while i < n:
|
||||||
|
ch = s[i]
|
||||||
|
if in_str is None:
|
||||||
|
# Check for line-comment starters at depth 0.
|
||||||
|
if ch == '/' and i + 1 < n and s[i + 1] == '/':
|
||||||
|
# Skip to newline.
|
||||||
|
while i < n and s[i] != '\n':
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch == '-' and i + 1 < n and s[i + 1] == '-' and (i == 0 or s[i - 1].isspace()):
|
||||||
|
while i < n and s[i] != '\n':
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if ch in ("'", '"', '`'):
|
||||||
|
in_str = ch
|
||||||
|
out.append(ch)
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
if ch == '\\' and i + 1 < n:
|
||||||
|
out.append(ch); out.append(s[i + 1]); i += 2
|
||||||
|
continue
|
||||||
|
if ch == in_str:
|
||||||
|
in_str = None
|
||||||
|
out.append(ch)
|
||||||
|
i += 1
|
||||||
|
return ''.join(out)
|
||||||
|
|
||||||
|
|
||||||
def process_hs_val(hs_val):
|
def process_hs_val(hs_val):
|
||||||
"""Process a raw HS attribute value: collapse whitespace, insert 'then' separators."""
|
"""Process a raw HS attribute value: collapse whitespace, insert 'then' separators."""
|
||||||
# Convert escaped newlines/tabs to real whitespace
|
# Convert escaped newlines/tabs to real whitespace
|
||||||
@@ -1187,8 +1226,8 @@ def process_hs_val(hs_val):
|
|||||||
hs_val = hs_val.replace('\x00QUOT\x00', '\\"')
|
hs_val = hs_val.replace('\x00QUOT\x00', '\\"')
|
||||||
# Strip line comments BEFORE newline collapse — once newlines become `then`,
|
# Strip line comments BEFORE newline collapse — once newlines become `then`,
|
||||||
# an unterminated `//` / ` --` comment would consume the rest of the input.
|
# an unterminated `//` / ` --` comment would consume the rest of the input.
|
||||||
hs_val = re.sub(r'//[^\n]*', '', hs_val)
|
# String-aware: `https://…` inside a backtick template must not be stripped.
|
||||||
hs_val = re.sub(r'(^|\s)--[^\n]*', r'\1', hs_val)
|
hs_val = _strip_hs_line_comments(hs_val)
|
||||||
cmd_kws = r'(?:set|put|get|add|remove|toggle|hide|show|if|repeat|for|wait|send|trigger|log|call|take|throw|return|append|tell|go|halt|settle|increment|decrement|fetch|make|install|measure|empty|reset|swap|default|morph|render|scroll|focus|select|pick|beep!)'
|
cmd_kws = r'(?:set|put|get|add|remove|toggle|hide|show|if|repeat|for|wait|send|trigger|log|call|take|throw|return|append|tell|go|halt|settle|increment|decrement|fetch|make|install|measure|empty|reset|swap|default|morph|render|scroll|focus|select|pick|beep!)'
|
||||||
hs_val = re.sub(r'\s{2,}(?=' + cmd_kws + r'\b)', ' then ', hs_val)
|
hs_val = re.sub(r'\s{2,}(?=' + cmd_kws + r'\b)', ' then ', hs_val)
|
||||||
hs_val = re.sub(r'\s*[\n\r]\s*', ' then ', hs_val)
|
hs_val = re.sub(r'\s*[\n\r]\s*', ' then ', hs_val)
|
||||||
|
|||||||
Reference in New Issue
Block a user