Hyperscript compiler/runtime:
- query target support in set/fire/put commands
- hs-set-prolog-hook! / hs-prolog-hook / hs-prolog in runtime
- runtime log-capture cleanup
Scripts: sx-loops-up/down, sx-hs-e-up/down, sx-primitives-down
Plans: datalog, elixir, elm, go, koka, minikanren, ocaml, hs-bucket-f,
designs (breakpoint, null-safety, step-limit, tell, cookies, eval,
plugin-system)
lib/prolog/hs-bridge.sx: initial hook-based bridge draft
lib/common-lisp/tests/runtime.sx: CL runtime tests
WASM: regenerate sx_browser.bc.js from updated hs sources
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.8 KiB
F13 — Step Limit + meta.caller (+5 → 100%)
Five tests currently timeout or produce wrong values due to two root causes:
step budget exhaustion and a missing meta implementation.
Tests
| # | Suite | Test | Failure |
|---|---|---|---|
| 198 | hs-upstream-core/runtime |
has proper stack from event handler |
wrong-value: meta.caller returns "" instead of an object with .meta.feature.type = "onFeature" |
| 200 | hs-upstream-core/runtime |
hypertrace is reasonable |
TIMEOUT (15s, step limit) |
| 615 | hs-upstream-expressions/in |
query template returns values |
TIMEOUT (37s, step limit) |
| 1197 | hs-upstream-repeat |
repeat forever works |
TIMEOUT (step limit) |
| 1198 | hs-upstream-repeat |
repeat forever works w/o keyword |
TIMEOUT (step limit) |
Root cause A — Step limit (tests 200, 615, 1197, 1198)
The runner sets HS_STEP_LIMIT=200000. Every CEK step consumed by any
expression in a test — including the double compilation warm-up guard blocks
that appear before the actual DOM test — counts against this shared budget.
repeat forever (1197, 1198)
The loop body terminates in exactly 5 iterations (if retVal == 5 then return).
This is bounded, not infinite. The step budget is exhausted before the loop
runs because two eval-expr-cek compilation warm-up calls each consume tens
of thousands of steps.
Fix: each warm-up guard compiles and discards a HS function definition. Those
calls are defensive (wrapped in guard that swallows errors). We do NOT need
to run the compiled code — the warm-up's purpose is just to ensure the
compiler doesn't crash, not to consume steps. The step counter should not tick
during compilation (compilation is a pure transform, not evaluation). If that's
impractical to gate, raise HS_STEP_LIMIT to 2000000 (10×).
hypertrace is reasonable (200)
Defines bar() → calls baz() → throws. Simple call chain. The "hypertrace"
in the test name implies the HS runtime trace recorder is active during the
test. If trace recording is on globally, every CEK step generates a trace entry
allocation. Fix: confirm whether trace recording is always-on in the test runner
and disable it by default (trace should only be on when explicitly requested).
Alternatively raise step limit.
query template returns values (615)
Uses <${"p"}/> — a CSS query selector built from a template string. Takes 37
seconds. Likely the template selector evaluation triggers repeated DOM scanning
or expensive string construction per step. Fix: profile with hs_test_run verbose=true to identify which step is slow. If it's a regex compilation
per-call, cache it. If step limit only, raise to 2M.
Unified fix: raise HS_STEP_LIMIT to 2000000
The simplest fix that unblocks all four timeout tests. In
tests/hs-run-filtered.js, change the default step limit. Per-test overrides
can still be set via HS_STEP_LIMIT env var for debugging.
If the query template test is still slow at 2M steps (37s × 10 = 370s, which
would be unacceptable), that test needs a separate performance fix — cache the
compiled regex/query from the template string rather than rebuilding it on every
access.
Root cause B — meta.caller not implemented (test 198)
The HS meta object is available inside any function call. It exposes:
meta.caller— the calling context objectmeta.caller.meta.feature.type— the HS feature type of the caller (e.g."onFeature"when called from anon clickhandler)
Test script:
def bar()
log meta.caller
return meta.caller
end
Triggered via on click put bar().meta.feature.type into my.innerHTML.
Expects "onFeature" in innerHTML. Currently gets "".
What meta needs
meta is a dict-like object injected into every function's execution context
at call time. Minimum fields for this test:
meta = {
:caller <the calling context — a dict with its own :meta field>
:element <the element the script is attached to>
}
meta.caller.meta.feature.type must return "onFeature" when called from an
on event handler. The feature type string "onFeature" is already used
internally (event handler features are tagged with this type).
Implementation
In lib/hyperscript/runtime.sx, at the point where a HS def function is
called:
-
Build a
metadict:{:caller calling-context :element current-element}where
calling-contextis the current runtime context dict (which includes its own:metafield with:feature {:type "onFeature"}for event handlers). -
Bind
metain the function's execution env. -
Ensure event handler contexts carry
{:meta {:feature {:type "onFeature"}}}.
This is an additive change — nothing currently uses meta, so no regression
risk.
Implementation checklist
Step A — Raise step limit
- In
tests/hs-run-filtered.js, change defaultHS_STEP_LIMITfrom200000to2000000. - Run tests 1197–1198:
hs_test_run(start=1197, end=1199)— expect 2/2. - Run test 615:
hs_test_run(start=615, end=616)— expect 1/1 or note if still too slow. - Run test 200:
hs_test_run(start=200, end=201)— expect 1/1.
Step B — meta.caller (test 198)
sx_find_allinlib/hyperscript/runtime.sxfor wheredeffunctions are called / where event handler contexts are constructed.- Add
metadict construction at call time; bind in function env. - Ensure
onhandler context carries{:meta {:feature {:type "onFeature"}}}. - Run test 198:
hs_test_run(start=198, end=199)— expect 1/1.
Step C — Query template performance (if still slow after step A)
- Profile
hs_test_run(start=615, end=616, step_limit=2000000, verbose=true). - If the CSS template query
<${"p"}/>rebuilds on every call, add a memoize cache keyed on the template result string. - Rerun — expect < 5s.
Step D — Full suite verification
- Run all ranges with raised step limit:
hs_test_run(start=0, end=201, step_limit=2000000)hs_test_run(start=201, end=616, step_limit=2000000)hs_test_run(start=616, end=1200, step_limit=2000000)hs_test_run(start=1200, end=1496, step_limit=2000000)
- Confirm all previously-passing tests still pass.
- Commit:
HS: raise step limit to 2M + meta.caller for onFeature stack (+5)
Risk
- Step limit raise: May make test suite slower overall (more steps to exhaust before timeout). But if tests pass quickly the limit is never reached. The 37s query-template test is the only real concern — if it genuinely needs 2M steps × (time per step), it needs a performance fix too.
meta.caller: Additive binding in function scope. Zero regression risk. The only complexity is constructing the right shape for the calling context chain — but since only one test exercises this and the shape is simple, the risk is low.