HS: chain .x after f(); translate window.X arrow setups — +5 functionCalls

Parser (lib/hyperscript/parser.sx):
- parse-poss case for "(" (function call) was building (call ...) and
  returning without recursing, so `f().x` lost the `.x` suffix and the
  compiler emitted (let ((it (f))) (hs-query-first ".x")). Now it tail-
  calls parse-poss on the constructed call so chains like f().x.y(),
  obj.method().prop, etc. parse correctly.

Generator (tests/playwright/generate-sx-tests.py):
- New js_expr_to_sx: translates arrow functions ((args) => body), object
  literals, simple property access / method calls / arith. Falls back
  through js_val_to_sx for primitives.
- New extract_window_setups: scans `evaluate(() => { window.X = Y })`
  blocks (with balanced-brace inner-body extraction) and returns
  (name, sx_value) pairs.
- Pattern 1 / Pattern 2 in generate_eval_only_test merge those window
  setups into the locals passed to eval-hs-locals, so HS expressions
  can reference globals defined by the test prelude.
- Object literal value parsing now goes through js_expr_to_sx first,
  so `{x: x, y: y}` yields `{:x x :y y}` (was `{:x "x" :y "y"}`).

Net: hs-upstream-expressions/functionCalls 0/12 → 5/12 (+5).
Smoke-checked put/set/scoping/possessiveExpression — no regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 11:10:11 +00:00
parent f8d30f50fb
commit 1bdd141178
4 changed files with 234 additions and 25 deletions

View File

@@ -5200,32 +5200,32 @@
;; ── expressions/functionCalls (12 tests) ──
(defsuite "hs-upstream-expressions/functionCalls"
(deftest "can access a property of a call's result"
(assert= (eval-hs "makePoint(3, 4).x") 3)
(assert= (eval-hs "makePoint(3, 4).y") 4)
(assert= (eval-hs-locals "makePoint(3, 4).x" (list (list (quote makePoint) (fn (x y) {:x x :y y})))) 3)
(assert= (eval-hs-locals "makePoint(3, 4).y" (list (list (quote makePoint) (fn (x y) {:x x :y y})))) 4)
)
(deftest "can chain calls on the result of a call"
(assert= (eval-hs "getObj().greet()") "hi")
(assert= (eval-hs-locals "getObj().greet()" (list (list (quote getObj) (fn () {:greet (fn () "hi")})))) "hi")
)
(deftest "can invoke function on object"
(assert= (eval-hs "obj.getValue()") "foo")
(assert= (eval-hs-locals "obj.getValue()" (list (list (quote obj) {:value "foo" :getValue "function () { return this.value }"}))) "foo")
)
(deftest "can invoke function on object w/ async arg"
(error "SKIP (untranslated): can invoke function on object w/ async arg"))
(deftest "can invoke function on object w/ async root & arg"
(error "SKIP (untranslated): can invoke function on object w/ async root & arg"))
(deftest "can invoke global function"
(assert= (eval-hs "identity(\"foo\")") "foo")
(assert= (eval-hs-locals "identity(\"foo\")" (list (list (quote identity) (fn (x) x)))) "foo")
)
(deftest "can invoke global function w/ async arg"
(error "SKIP (untranslated): can invoke global function w/ async arg"))
(deftest "can pass an array literal as an argument"
(assert= (eval-hs "sum([1, 2, 3, 4])") 10)
(assert= (eval-hs-locals "sum([1, 2, 3, 4])" (list (list (quote sum) (fn (arr) (host-call arr "reduce" (fn (a b) (+ a b)) 0))))) 10)
)
(deftest "can pass an expression as an argument"
(assert= (eval-hs "double(3 + 4)") 14)
(assert= (eval-hs-locals "double(3 + 4)" (list (list (quote double) (fn (n) (* n 2))))) 14)
)
(deftest "can pass an object literal as an argument"
(assert= (eval-hs "getName({name: 'Alice'})") "Alice")
(assert= (eval-hs-locals "getName({name: 'Alice'})" (list (list (quote getName) (fn (o) (host-get o "name"))))) "Alice")
)
(deftest "can pass multiple arguments"
(hs-cleanup!)
@@ -5237,7 +5237,7 @@
(assert= (dom-text-content _el-div) "6")
))
(deftest "can pass no arguments"
(assert= (eval-hs "getFortyTwo()") 42)
(assert= (eval-hs-locals "getFortyTwo()" (list (list (quote getFortyTwo) (fn () 42)))) 42)
)
)
@@ -5842,7 +5842,7 @@
(assert= (eval-hs-locals "doh of foo.bar" (list (list (quote foo) {:bar {:doh "foo"}}))) "foo")
)
(deftest "property access on function result"
(assert= (eval-hs "makeObj().name") "hi")
(assert= (eval-hs-locals "makeObj().name" (list (list (quote makeObj) (fn () {:name "hi"})))) "hi")
)
(deftest "works properly w/ boolean properties"
(hs-cleanup!)