# 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 object
- `meta.caller.meta.feature.type` — the HS feature type of the caller
  (e.g. `"onFeature"` when called from an `on click` handler)

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:

1. Build a `meta` dict:
   ```
   {:caller calling-context :element current-element}
   ```
   where `calling-context` is the current runtime context dict (which includes
   its own `:meta` field with `:feature {:type "onFeature"}` for event handlers).

2. Bind `meta` in the function's execution env.

3. 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
1. In `tests/hs-run-filtered.js`, change default `HS_STEP_LIMIT` from `200000`
   to `2000000`.
2. Run tests 1197–1198: `hs_test_run(start=1197, end=1199)` — expect 2/2.
3. Run test 615: `hs_test_run(start=615, end=616)` — expect 1/1 or note if
   still too slow.
4. Run test 200: `hs_test_run(start=200, end=201)` — expect 1/1.

### Step B — `meta.caller` (test 198)
5. `sx_find_all` in `lib/hyperscript/runtime.sx` for where `def` functions are
   called / where event handler contexts are constructed.
6. Add `meta` dict construction at call time; bind in function env.
7. Ensure `on` handler context carries `{:meta {:feature {:type "onFeature"}}}`.
8. Run test 198: `hs_test_run(start=198, end=199)` — expect 1/1.

### Step C — Query template performance (if still slow after step A)
9. Profile `hs_test_run(start=615, end=616, step_limit=2000000, verbose=true)`.
10. If the CSS template query `<${"p"}/>` rebuilds on every call, add a memoize
    cache keyed on the template result string.
11. Rerun — expect < 5s.

### Step D — Full suite verification
12. 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)`
13. Confirm all previously-passing tests still pass.
14. 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.
