Tests with _=\"...\" attribute delimiters were garbled because
HTMLParser interpreted the backslash-quote as content, not delimiters.
Now html.replace('\"', '"') normalizes before parsing.
Fixes ~15 tests across toggle, transition, and other categories
that were previously running with corrupted HS source.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parser:
- Relax (number? v) to v in parse-one-transition so (expr)unit works
- Add (match-kw "then") before parse-cmd-list in parse-for-cmd
- Handle "indexed by" syntax alongside "index" in for loops
- Add "indexed" to hs-keywords to prevent unit-suffix consumption
Compiler:
- Use map-indexed instead of for-each for indexed for-loops
Test generator:
- Preserve \" escapes in process_hs_val via placeholder/restore
Mock DOM:
- Coerce insertAdjacentHTML values via dom_stringify (match browser)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parser:
- `add VALUE to :var` → (add-value) for array append
- `remove VALUE from :var` → (remove-value) for array removal
- `toggle .foo for 10ms` → (toggle-class-for) with duration
- `append VALUE` without `to` → implicit target (it)
- `set {obj} on target` → (set-on) for object property spread
- `repeat in` body: remove spurious nil (body at index 3→2)
- Keywords followed by `(` parsed as function calls (fixes `increment()`)
Compiler:
- Handle add-value, remove-value, toggle-class-for, set-on AST nodes
- Local variables (`set :var`) use `define` instead of `set!`
Runtime:
- hs-add-to!: append value to list
- hs-remove-from!: filter value from list
- hs-set-on!: spread dict properties onto target
- `as String` for lists: comma-join (JS Array.toString compat)
Tests:
- eval-hs/eval-hs-with-me: guard for hs-return exceptions
(return compiles to raise, needs handler to extract value)
Parse errors: 20→12 (8 fixed). Remaining: 6 embedded HTML quotes
(tokenizer), 6 transition template values `(expr)px`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
callable? in boot-helpers.sx checked for "native-fn" but type-of returns
"function" for NativeFn — broke make-spread and all native fn dispatch
in aser. Restore 20 behavioral tests replaced with NOT IMPLEMENTED stubs
by the test regeneration commit. Add host-* platform primitive stubs to
sx_server.ml so boot-helpers.sx loads without errors server-side.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Compiler: return compiles to (raise (list "hs-return" value))
- Compiler: def wraps body in guard to catch hs-return exceptions
- Compiler: def params extract name from (ref name) nodes
- Test generator: extract <script type="text/hyperscript"> blocks
and compile def functions as setup before tests
- Test generator: add eval-hs-with-me for {me: N} opts
The return mechanism enables repeat-forever with early exit via return.
Direct SX guard/raise works (returns correct value), but the compiled
HS repeat-forever thunk body needs further debugging for full coverage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle result["foo"] and result.foo property access after eval-hs
- Handle { locals: { x: 5, y: 5 } } opts with nested braces
- Handle { me: N } opts via eval-hs-with-me helper
- Add eval-hs-with-me to test framework for "I am between" tests
- Use host-get for property access on host handles (JSON.parse results)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parser: skip unit suffix when next ident is a comparison keyword
(starts, ends, contains, matches, is, does, in, precedes, follows).
Fixes "123 starts with '12'" returning "123starts" instead of true.
eval-hs: use hs-compile directly instead of hs-to-sx-from-source with
"return " prefix, which was causing the parser to consume the comparison
as a string suffix.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- eval-hs: new test helper that compiles+evaluates a HS expression and
returns its result. Uses hs-to-sx-from-source with "return " prefix.
- Generator now emits eval-hs calls for expression-only tests
- no suite: 4/5 pass (was 0/5)
- evalStatically: 5/8 pass (was 0/8 stubs)
- pick: 7/7 pass (was 0/7 stubs)
- mathOperator: 3/5 pass (type issues on array concat)
477/831 (57.4%), +69 from session baseline of 408.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- parse_html now captures ALL elements (not just top-level) with
parent-child relationships
- emit_element_setup uses three phases: attributes, DOM tree, activation
- ref() maps positional names (d1, d2) to top-level elements only
- dom-scope: 9→14 (+5), reset: 3→6 (+3), take: 2→3, parser: 2→3
Net 0 due to regressions in dialog/halt/closest (needs investigation).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Don't insert 'then' inside for-in loop bodies or after 'repeat N times'
(fixes repeat from 1/30 → 5/30)
- Allow HS sources ending with " when they don't contain embedded HTML
(fixes set from 6/25 → 10/25, enables 18 previously-skipped tests)
- Fix assert= argument order: (actual expected), not (expected actual)
(error messages now correctly report Expected/Got)
395 → 402/831 (+7)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- text-layout.sx added to WASM bytecode pipeline (9K compiled)
- Fix multi-list map calls (map-indexed + nth instead of map fn list1 list2)
- pretext-layout-lines and pretext-position-line moved to library exports
- Browser load-sxbc: handle VmSuspended for import, copy library exports
to global_env after module load (define-library export fix)
- compile-modules.js: text-layout in SOURCE_MAP, FILES, and entry deps
- Island uses library functions (break-lines, pretext-layout-lines)
instead of inlining — runs on bytecode VM when exports resolve
Known issue: define-library exports don't propagate to browser global env
yet. The load-sxbc import suspension handler resumes correctly but
bind_import_set doesn't fire. Needs deeper investigation into how the
WASM kernel's define-library registers exports vs how other libraries
(adapter-html, tw) make their exports available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixed then insertion to only trigger before known HS command keywords
(set, put, add, remove, toggle, etc.) via lookahead regex, instead of
on all multi-space sequences. Prevents breaking single-command
expressions with wide spacing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Biggest win: HS sources from upstream HTML had newlines replaced with
spaces, losing command separation. Now multi-space sequences become
'then' keywords, matching _hyperscript's implicit newline-as-separator
behavior. +42 tests passing.
Parser: 'is between X and Y', 'is not between', 'starts with',
'ends with' comparison operators.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Generator: converts no-HTML tests with run("expr").toBe(val) patterns
to (assert= val (eval-hs "expr")). 111→92 stubs (-19 converted).
- Parser: multi-class add/remove (.foo .bar collects into multi-add-class)
- Compiler: multi-add-class/multi-remove-class emit (do (dom-add-class..))
- Test runner: drives IO suspension in per-test evaluate for async tests
- Parser: catch/finally support in on handlers, cmd terminators
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixed ref() to map upstream JS variable names to let-bound SX variables
using element context (tag→var, id→var, make-return→last-var). Fixes
if (0→14/19), put (14→18), on (20→23), and other categories where the
upstream test uses make() return variables like d1, div, btn.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrote test architecture: deferred execution. Tests register thunks during
file load (try-call redefined to append to _test-registry), then the
Playwright loop runs each individually with 3s timeout via Promise.race.
Hanging tests (parser infinite loops) fail with TIMEOUT and trigger page
reboot. No tests are hidden or skipped.
Fixed generator: proper quote escaping for HS sources with embedded quotes,
sanitized comments to avoid SX parser special chars.
831 tests registered, 424 pass, 407 fail honestly:
- 22 perfect categories (empty, dialog, morph, default, reset, scroll, etc.)
- Major gaps: if 0/19, wait 0/7, take 0/12, repeat 2/30, set 4/25
- Timeout failures from parser hangs on unsupported syntax
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reset to last known-good state (908f4f80) where links, stepper, and
islands all work, then recovered all hyperscript implementation,
conformance tests, behavioral tests, Playwright specs, site sandbox,
IO-aware server loading, and upstream test suite from f271c88a.
Excludes runtime changes (VM resolve hook, VmSuspended browser handler,
sx_ref.ml guard recovery) that need careful re-integration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>