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>
329 lines
16 KiB
Plaintext
329 lines
16 KiB
Plaintext
;; _hyperscript conformance — 222 tests from v0.9.14
|
|
;;
|
|
;; OCaml: loaded by run_tests.exe, uses eval-expr-cek
|
|
;; Sandbox: sx_playwright mode=sandbox stack=hs files=[this]
|
|
;; expr=(do (hs-conf-run-all) (hs-conf-report))
|
|
|
|
;; ── Counters ────────────────────────────────────────────────────
|
|
(define hs-conf-pass 0)
|
|
(define hs-conf-fail 0)
|
|
(define hs-conf-fails (list))
|
|
|
|
;; ── eval-hs: sandbox version uses cek-eval ──────────────────────
|
|
(define
|
|
eval-hs
|
|
(fn
|
|
(src &rest opts)
|
|
(let
|
|
((sx (hs-to-sx (hs-compile src)))
|
|
(ctx (if (> (len opts) 0) (first opts) nil)))
|
|
(let
|
|
((bindings (list (list (quote me) nil) (list (quote it) nil) (list (quote result) nil) (list (quote hs-add) (list (quote quote) hs-add)) (list (quote hs-falsy?) (list (quote quote) hs-falsy?)) (list (quote hs-strict-eq) (list (quote quote) hs-strict-eq)) (list (quote hs-type-check) (list (quote quote) hs-type-check)) (list (quote hs-type-check-strict) (list (quote quote) hs-type-check-strict)) (list (quote hs-matches?) (list (quote quote) hs-matches?)) (list (quote hs-coerce) (list (quote quote) hs-coerce)) (list (quote hs-contains?) (list (quote quote) hs-contains?)) (list (quote hs-empty?) (list (quote quote) hs-empty?)) (list (quote hs-first) (list (quote quote) hs-first)) (list (quote hs-last) (list (quote quote) hs-last)) (list (quote hs-make-object) (list (quote quote) hs-make-object)) (list (quote hs-template) (list (quote quote) hs-template)) (list (quote modulo) (list (quote quote) modulo)) (list (quote foo) (list (quote quote) {:bar {:doh "foo"} :foo "foo"})) (list (quote identity) (list (quote quote) (fn (x) x))) (list (quote obj) (list (quote quote) {:getValue (fn () 42)})) (list (quote func1) (list (quote quote) (fn () "a"))) (list (quote func2) (list (quote quote) (fn () "b"))) (list (quote value) "<b>hello</b>") (list (quote d) "2024-01-01") (list (quote record) (list (quote quote) {:favouriteColour "bleaux" :age 21 :name "John Connor"})))))
|
|
(do
|
|
(when
|
|
ctx
|
|
(do
|
|
(when
|
|
(get ctx "me")
|
|
(append!
|
|
bindings
|
|
(list (quote me) (list (quote quote) (get ctx "me")))))
|
|
(when
|
|
(get ctx "locals")
|
|
(for-each
|
|
(fn
|
|
(k)
|
|
(append!
|
|
bindings
|
|
(list
|
|
(make-symbol k)
|
|
(list (quote quote) (get (get ctx "locals") k)))))
|
|
(keys (get ctx "locals"))))))
|
|
(cek-eval (list (quote let) bindings sx)))))))
|
|
|
|
;; ── Fixture runner ──────────────────────────────────────────────
|
|
(define hs-conf-run-fixture
|
|
(fn (f)
|
|
(let ((src (get f "src"))
|
|
(expected (get f "expected"))
|
|
(ctx (if (or (get f "locals") (get f "me"))
|
|
{"locals" (get f "locals") "me" (get f "me")} nil)))
|
|
(let ((ok (try-call (fn ()
|
|
(let ((result (if ctx (eval-hs src ctx) (eval-hs src))))
|
|
(if (= result expected)
|
|
(set! hs-conf-pass (+ hs-conf-pass 1))
|
|
(do (set! hs-conf-fail (+ hs-conf-fail 1))
|
|
(append! hs-conf-fails (str src " => " result " exp " expected)))))))))
|
|
(when (not (get ok "ok"))
|
|
(do (set! hs-conf-fail (+ hs-conf-fail 1))
|
|
(append! hs-conf-fails (str "ERR: " src))))))))
|
|
|
|
(define hs-conf-run-all
|
|
(fn () (for-each hs-conf-run-fixture hs-conf-all-fixtures)))
|
|
|
|
(define hs-conf-report
|
|
(fn () (str hs-conf-pass "/" (+ hs-conf-pass hs-conf-fail) " pass, " hs-conf-fail " fail")))
|
|
|
|
;; ── Fixtures ────────────────────────────────────────────────────
|
|
(define hs-conf-all-fixtures (list
|
|
{"src" "[1, 2, 3]" "expected" (list 1 2 3)}
|
|
{"src" "[]" "expected" (list)}
|
|
{"src" "[true]" "expected" (list true)}
|
|
{"src" "[true, false]" "expected" (list true false)}
|
|
{"src" "null as String" "expected" nil}
|
|
{"src" "10 as String" "expected" "10"}
|
|
{"src" "true as String" "expected" "true"}
|
|
{"src" "'10' as Int" "expected" 10}
|
|
{"src" "'10.4' as Int" "expected" 10}
|
|
{"src" "'10' as Float" "expected" 10}
|
|
{"src" "'10.4' as Float" "expected" 10.4}
|
|
{"src" "'10.4' as Fixed" "expected" "10"}
|
|
{"src" "'10.4899' as Fixed:2" "expected" "10.49"}
|
|
{"src" "'10' as Number" "expected" 10}
|
|
{"src" "'10.4' as Number" "expected" 10.4}
|
|
{"src" "1 as Date" "expected" 1}
|
|
{"src" "1 as a Date" "expected" 1}
|
|
{"src" "{foo:'bar'} as JSON" "expected" "{\"foo\":\"bar\"}"}
|
|
{"src" "'{\"foo\":\"bar\"}' as Object" "expected" "bar"}
|
|
{"src" "'{\"foo\":\"bar\"}' as an Object" "expected" "bar"}
|
|
{"src" "x as Object" "expected" "bar"}
|
|
{"src" "x as Values" "expected" "John"}
|
|
{"src" "d as HTML" "expected" "this-is-html"}
|
|
{"src" "value as HTML" "expected" "123"}
|
|
{"src" "value as Fragment" "expected" 1}
|
|
{"src" "1 as Foo" "expected" "foo1"}
|
|
{"src" "1 as Foo:Bar" "expected" "Bar1"}
|
|
{"src" "func(async 1)" "expected" 1}
|
|
{"src" "\\\\-> true" "expected" true}
|
|
{"src" "\\ x -> x" "expected" true "locals" {"x" true}}
|
|
{"src" "\\ x, y -> y" "expected" true "locals" {"x" false "y" true}}
|
|
{"src" "['a', 'ab', 'abc'].map(\\\\ s -> s.length )" "expected" (list 1 2 3)}
|
|
{"src" "true" "expected" true}
|
|
{"src" "false" "expected" false}
|
|
{"src" ".badClassThatDoesNotHaveAnyElements" "expected" 0}
|
|
{"src" "1 < 2" "expected" true}
|
|
{"src" "2 < 1" "expected" false}
|
|
{"src" "2 < 2" "expected" false}
|
|
{"src" "1 <= 2" "expected" true}
|
|
{"src" "2 <= 1" "expected" false}
|
|
{"src" "2 <= 2" "expected" true}
|
|
{"src" "1 > 2" "expected" false}
|
|
{"src" "2 > 1" "expected" true}
|
|
{"src" "2 > 2" "expected" false}
|
|
{"src" "1 >= 2" "expected" false}
|
|
{"src" "2 >= 1" "expected" true}
|
|
{"src" "2 >= 2" "expected" true}
|
|
{"src" "1 == 2" "expected" false}
|
|
{"src" "2 == 1" "expected" false}
|
|
{"src" "2 == 2" "expected" true}
|
|
{"src" "1 === 2" "expected" false}
|
|
{"src" "2 === 1" "expected" false}
|
|
{"src" "2 === 2" "expected" true}
|
|
{"src" "1 != 2" "expected" true}
|
|
{"src" "2 != 1" "expected" true}
|
|
{"src" "2 != 2" "expected" false}
|
|
{"src" "1 !== 2" "expected" true}
|
|
{"src" "2 !== 1" "expected" true}
|
|
{"src" "2 !== 2" "expected" false}
|
|
{"src" "1 is 2" "expected" false}
|
|
{"src" "2 is 1" "expected" false}
|
|
{"src" "2 is 2" "expected" true}
|
|
{"src" "1 equals 2" "expected" false}
|
|
{"src" "2 equals 1" "expected" false}
|
|
{"src" "2 equals 2" "expected" true}
|
|
{"src" "1 is equal to 2" "expected" false}
|
|
{"src" "2 is equal to 1" "expected" false}
|
|
{"src" "2 is equal to 2" "expected" true}
|
|
{"src" "1 is really equal to 2" "expected" false}
|
|
{"src" "2 is really equal to 1" "expected" false}
|
|
{"src" "2 is really equal to '2'" "expected" false}
|
|
{"src" "2 is really equal to 2" "expected" true}
|
|
{"src" "1 really equals 2" "expected" false}
|
|
{"src" "2 really equals 1" "expected" false}
|
|
{"src" "2 really equals 2" "expected" true}
|
|
{"src" "1 is not 2" "expected" true}
|
|
{"src" "2 is not 1" "expected" true}
|
|
{"src" "2 is not 2" "expected" false}
|
|
{"src" "1 is not equal to 2" "expected" true}
|
|
{"src" "2 is not equal to 1" "expected" true}
|
|
{"src" "2 is not equal to 2" "expected" false}
|
|
{"src" "1 is not really equal to 2" "expected" true}
|
|
{"src" "2 is not really equal to 1" "expected" true}
|
|
{"src" "2 is not really equal to '2'" "expected" true}
|
|
{"src" "2 is not really equal to 2" "expected" false}
|
|
{"src" "1 is in [1, 2]" "expected" true}
|
|
{"src" "2 is in [1, 2]" "expected" true}
|
|
{"src" "3 is in [1, 2]" "expected" false}
|
|
{"src" "3 is in null" "expected" false}
|
|
{"src" "1 is not in [1, 2]" "expected" false}
|
|
{"src" "2 is not in [1, 2]" "expected" false}
|
|
{"src" "3 is not in [1, 2]" "expected" true}
|
|
{"src" "3 is not in null" "expected" true}
|
|
{"src" "I am in [1, 2]" "expected" true "me" 1}
|
|
{"src" "I am in [1, 2]" "expected" true "me" 2}
|
|
{"src" "I am in [1, 2]" "expected" false "me" 3}
|
|
{"src" "I am in null" "expected" false}
|
|
{"src" "I am not in [1, 2]" "expected" false "me" 1}
|
|
{"src" "I am not in [1, 2]" "expected" false "me" 2}
|
|
{"src" "I am not in [1, 2]" "expected" true "me" 3}
|
|
{"src" "I am not in null" "expected" true}
|
|
{"src" "'a' matches '.*'" "expected" true}
|
|
{"src" "'a' matches 'b'" "expected" false}
|
|
{"src" "'a' does not match '.*'" "expected" false}
|
|
{"src" "'a' does not match 'b'" "expected" true}
|
|
{"src" "I contain that" "expected" true "me" (list 1 2 3) "locals" {"that" 1}}
|
|
{"src" "that contains me" "expected" true "me" 1 "locals" {"that" (list 1 2 3)}}
|
|
{"src" "I include that" "expected" true "me" "foobar" "locals" {"that" "foo"}}
|
|
{"src" "that includes me" "expected" true "me" "foo" "locals" {"that" "foobar"}}
|
|
{"src" "undefined is empty" "expected" true}
|
|
{"src" "'' is empty" "expected" true}
|
|
{"src" "[] is empty" "expected" true}
|
|
{"src" "'not empty' is empty" "expected" false}
|
|
{"src" "1000 is empty" "expected" false}
|
|
{"src" "[1,2,3] is empty" "expected" false}
|
|
{"src" ".aClassThatDoesNotExist is empty" "expected" true}
|
|
{"src" "undefined is not empty" "expected" false}
|
|
{"src" "'' is not empty" "expected" false}
|
|
{"src" "[] is not empty" "expected" false}
|
|
{"src" "'not empty' is not empty" "expected" true}
|
|
{"src" "1000 is not empty" "expected" true}
|
|
{"src" "[1,2,3] is not empty" "expected" true}
|
|
{"src" "null is a String" "expected" true}
|
|
{"src" "null is a String!" "expected" false}
|
|
{"src" "'' is a String!" "expected" true}
|
|
{"src" "null is not a String" "expected" false}
|
|
{"src" "null is not a String!" "expected" true}
|
|
{"src" "'' is not a String!" "expected" false}
|
|
{"src" "null is an String" "expected" true}
|
|
{"src" "null is an String!" "expected" false}
|
|
{"src" "'' is an String!" "expected" true}
|
|
{"src" "null is not an String" "expected" false}
|
|
{"src" "null is not an String!" "expected" true}
|
|
{"src" "'' is not an String!" "expected" false}
|
|
{"src" "1 is less than 2" "expected" true}
|
|
{"src" "2 is less than 1" "expected" false}
|
|
{"src" "2 is less than 2" "expected" false}
|
|
{"src" "1 is less than or equal to 2" "expected" true}
|
|
{"src" "2 is less than or equal to 1" "expected" false}
|
|
{"src" "2 is less than or equal to 2" "expected" true}
|
|
{"src" "1 is greater than 2" "expected" false}
|
|
{"src" "2 is greater than 1" "expected" true}
|
|
{"src" "2 is greater than 2" "expected" false}
|
|
{"src" "1 is greater than or equal to 2" "expected" false}
|
|
{"src" "2 is greater than or equal to 1" "expected" true}
|
|
{"src" "2 is greater than or equal to 2" "expected" true}
|
|
{"src" "undefined does not exist" "expected" true}
|
|
{"src" "null does not exist" "expected" true}
|
|
{"src" "#doesNotExist does not exist" "expected" true}
|
|
{"src" ".aClassThatDoesNotExist does not exist" "expected" true}
|
|
{"src" "<.aClassThatDoesNotExist/> does not exist" "expected" true}
|
|
{"src" "<body/> does not exist" "expected" false}
|
|
{"src" "cookies.clearAll()" "expected" nil}
|
|
{"src" "cookies.foo" "expected" nil}
|
|
{"src" "set cookies.foo to 'bar'" "expected" "bar"}
|
|
{"src" "cookies.foo" "expected" "bar"}
|
|
{"src" "set cookies.foo to 'bar'" "expected" "bar"}
|
|
{"src" "cookies.foo" "expected" "bar"}
|
|
{"src" "set cookies.foo to 'doh'" "expected" "doh"}
|
|
{"src" "cookies.foo" "expected" "doh"}
|
|
{"src" "set cookies.foo to 'bar'" "expected" nil}
|
|
{"src" "cookies.clear('foo')" "expected" nil}
|
|
{"src" "cookies.foo" "expected" nil}
|
|
{"src" "set cookies.foo to 'bar'" "expected" true}
|
|
{"src" "for x in cookies me.push(x.name) then you.push(x.value) end" "expected" true}
|
|
{"src" "identity(\"foo\")" "expected" "foo"}
|
|
{"src" "obj.getValue()" "expected" "foo"}
|
|
{"src" "1 in [1, 2, 3]" "expected" (list 1)}
|
|
{"src" "[1, 3] in [1, 2, 3]" "expected" (list 1 3)}
|
|
{"src" "[1, 3, 4] in [1, 2, 3]" "expected" (list 1 3)}
|
|
{"src" "[4, 5, 6] in [1, 2, 3]" "expected" (list)}
|
|
{"src" "true and false" "expected" false}
|
|
{"src" "true or false" "expected" true}
|
|
{"src" "true and true and false" "expected" false}
|
|
{"src" "true and (false or true)" "expected" true}
|
|
{"src" "func1() and func2()" "expected" false}
|
|
{"src" "func1() or func2()" "expected" true}
|
|
{"src" "1 + 1" "expected" 2}
|
|
{"src" "'a' + 'b'" "expected" "ab"}
|
|
{"src" "1 - 1" "expected" 0}
|
|
{"src" "1 * 2" "expected" 2}
|
|
{"src" "1 / 2" "expected" 0.5}
|
|
{"src" "3 mod 2" "expected" 1}
|
|
{"src" "1 + 2 + 3" "expected" 6}
|
|
{"src" "1 + (2 * 3)" "expected" 7}
|
|
{"src" "no null" "expected" true}
|
|
{"src" "no 'thing'" "expected" false}
|
|
{"src" "no []" "expected" true}
|
|
{"src" "no .aClassThatDoesNotExist" "expected" true}
|
|
{"src" "no ['thing']" "expected" false}
|
|
{"src" "not true" "expected" false}
|
|
{"src" "not false" "expected" true}
|
|
{"src" "not not true" "expected" true}
|
|
{"src" "null" "expected" nil}
|
|
{"src" "-1" "expected" -1}
|
|
{"src" "1" "expected" 1}
|
|
{"src" "1.1" "expected" 1.1}
|
|
{"src" "1e6" "expected" 1000000}
|
|
{"src" "1e-6" "expected" 0.000001}
|
|
{"src" "1.1e6" "expected" 1100000}
|
|
{"src" "1.1e-6" "expected" 0.0000011}
|
|
{"src" "1234567890.1234567890" "expected" 1234567890.1234567}
|
|
{"src" "{}" "expected" {}}
|
|
{"src" "{foo:true}" "expected" {"foo" true}}
|
|
{"src" "{foo:true, bar:false}" "expected" {"foo" true "bar" false}}
|
|
{"src" "{\"foo\":true, \"bar\":false}" "expected" {"foo" true "bar" false}}
|
|
{"src" "{-foo:true, bar-baz:false}" "expected" {"-foo" true "bar-baz" false}}
|
|
{"src" "{foo:true, bar-baz:false,}" "expected" {"foo" true "bar-baz" false}}
|
|
{"src" "{[foo]:true, [bar()]:false}" "expected" {"bar" true "foo" false}}
|
|
{"src" "the first of [1, 2, 3]" "expected" 1}
|
|
{"src" "the last of [1, 2, 3]" "expected" 3}
|
|
{"src" "the first of null" "expected" nil}
|
|
{"src" "foo's foo" "expected" "foo" "locals" {"foo" {"foo" "foo"}}}
|
|
{"src" "foo's foo" "expected" "foo"}
|
|
{"src" "my foo" "expected" "foo" "me" {"foo" "foo"}}
|
|
{"src" "my foo" "expected" nil}
|
|
{"src" "its foo" "expected" "foo" "locals" {"it" {"foo" "foo"}}}
|
|
{"src" "its foo" "expected" nil}
|
|
{"src" "foo.foo" "expected" "foo" "locals" {"foo" {"foo" "foo"}}}
|
|
{"src" "foo.foo" "expected" "foo"}
|
|
{"src" "foo of foo" "expected" "foo" "locals" {"foo" {"foo" "foo"}}}
|
|
{"src" "bar.doh of foo" "expected" "foo" "locals" {"foo" {"bar" {"doh" "foo"}}}}
|
|
{"src" "doh of foo.bar" "expected" "foo" "locals" {"foo" {"bar" {"doh" "foo"}}}}
|
|
{"src" "<.badClassThatDoesNotHaveAnyElements/>" "expected" 0}
|
|
{"src" "some null" "expected" false}
|
|
{"src" "some 'thing'" "expected" true}
|
|
{"src" "some []" "expected" false}
|
|
{"src" "some .aClassThatDoesNotExist" "expected" false}
|
|
{"src" "some <html/>" "expected" true}
|
|
{"src" "some ['thing']" "expected" true}
|
|
{"src" "1em" "expected" "1em"}
|
|
{"src" "1px" "expected" "1px"}
|
|
{"src" "-1px" "expected" "-1px"}
|
|
{"src" "100%" "expected" "100%"}
|
|
{"src" "1 em" "expected" "1em"}
|
|
{"src" "1 px" "expected" "1px"}
|
|
{"src" "100 %" "expected" "100%"}
|
|
{"src" "(0 + 1) em" "expected" "1em"}
|
|
{"src" "(0 + 1) px" "expected" "1px"}
|
|
{"src" "(100 + 0) %" "expected" "100%"}
|
|
{"src" "\"foo\"" "expected" "foo"}
|
|
{"src" "\"fo'o\"" "expected" "fo'o"}
|
|
{"src" "'foo'" "expected" "foo"}
|
|
{"src" "`$1`" "expected" "1"}
|
|
{"src" "`$window.foo`" "expected" "foo"}
|
|
{"src" "`${window.foo}`" "expected" "foo"}
|
|
{"src" "`${1 + 2}`" "expected" "3"}
|
|
{"src" "` ${1 + 2} ${1 + 2} `" "expected" " 3 3 "}
|
|
{"src" "`${1 + 2} ${1 + 2} `" "expected" "3 3 "}
|
|
{"src" "`${1 + 2}${1 + 2} `" "expected" "33 "}
|
|
{"src" "`${1 + 2} ${1 + 2}`" "expected" "3 3"}
|
|
{"src" "`<div age=\"${record.age}\" style=\"color:${record.favouriteColour}\">${record.name}</div>`" "expected" "<div age=\"21\" style=\"color:bleaux\">John Connor</div>"}
|
|
{"src" "`https://${foo}`" "expected" "https://bar" "locals" {"foo" "bar"}}
|
|
{"src" "foo" "expected" 42 "locals" {"foo" 42}}
|
|
{"src" "'foo' : String" "expected" "foo"}
|
|
{"src" "null : String" "expected" ""}
|
|
{"src" "true : String" "expected" "true"}
|
|
{"src" "'foo' : String!" "expected" true}
|
|
{"src" "null : String!" "expected" false}
|
|
))
|