Playwright sandbox: offline browser test environment for WASM kernel
New sx_playwright mode="sandbox" — injects the WASM kernel into about:blank with full FFI, IO suspension tracing, and real DOM. No server needed. Predefined stacks: core (kernel only), web (full web stack), hs (+ hyperscript), test (+ test framework). Custom files and setup expressions supported. Reproduces the host-callback IO suspension bug: direct callFn chains 6/6 suspensions correctly, but host-callback → addEventListener → _driveAsync only completes 1/6. Bug is in the _driveAsync resume chain context. Also: debug.sx mock DOM harness, test_hs_repeat.js Node.js reproduction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -333,7 +333,7 @@
|
||||
(hs-to-sx (nth ast 1))
|
||||
(hs-to-sx (nth ast 2))))
|
||||
((= head (quote empty?))
|
||||
(list (quote empty?) (hs-to-sx (nth ast 1))))
|
||||
(list (quote hs-empty?) (hs-to-sx (nth ast 1))))
|
||||
((= head (quote exists?))
|
||||
(list
|
||||
(quote not)
|
||||
@@ -356,10 +356,13 @@
|
||||
(hs-to-sx (nth ast 2))
|
||||
(hs-to-sx (nth ast 1))))
|
||||
((= head (quote of))
|
||||
(list
|
||||
(quote get)
|
||||
(hs-to-sx (nth ast 2))
|
||||
(hs-to-sx (nth ast 1))))
|
||||
(let
|
||||
((prop (hs-to-sx (nth ast 1)))
|
||||
(target (hs-to-sx (nth ast 2))))
|
||||
(cond
|
||||
((= prop (quote first)) (list (quote first) target))
|
||||
((= prop (quote last)) (list (quote last) target))
|
||||
(true (list (quote get) target prop)))))
|
||||
((= head "!=")
|
||||
(list
|
||||
(quote not)
|
||||
|
||||
@@ -187,20 +187,26 @@
|
||||
((and (= typ "keyword") (= val "some"))
|
||||
(do
|
||||
(adv!)
|
||||
(let
|
||||
((var-name (tp-val)))
|
||||
(do
|
||||
(adv!)
|
||||
(match-kw "in")
|
||||
(let
|
||||
((collection (parse-expr)))
|
||||
(do
|
||||
(match-kw "with")
|
||||
(list
|
||||
(quote some)
|
||||
var-name
|
||||
collection
|
||||
(parse-expr))))))))
|
||||
(if
|
||||
(and
|
||||
(= (tp-type) "ident")
|
||||
(> (len tokens) (+ p 1))
|
||||
(= (get (nth tokens (+ p 1)) "value") "in"))
|
||||
(let
|
||||
((var-name (tp-val)))
|
||||
(do
|
||||
(adv!)
|
||||
(match-kw "in")
|
||||
(let
|
||||
((collection (parse-expr)))
|
||||
(do
|
||||
(match-kw "with")
|
||||
(list
|
||||
(quote some)
|
||||
var-name
|
||||
collection
|
||||
(parse-expr))))))
|
||||
(list (quote not) (list (quote no) (parse-expr))))))
|
||||
((and (= typ "keyword") (= val "every"))
|
||||
(do
|
||||
(adv!)
|
||||
@@ -277,7 +283,7 @@
|
||||
(do
|
||||
(adv!)
|
||||
(let
|
||||
((strict (if (string-ends-with? type-name "!") (string-slice type-name 0 (- (len type-name) 1)) nil)))
|
||||
((strict (if (= (nth type-name (- (len type-name) 1)) "!") (string-slice type-name 0 (- (len type-name) 1)) nil)))
|
||||
(if
|
||||
strict
|
||||
(list
|
||||
@@ -327,7 +333,7 @@
|
||||
(do
|
||||
(adv!)
|
||||
(let
|
||||
((strict (if (string-ends-with? type-name "!") (string-slice type-name 0 (- (len type-name) 1)) nil)))
|
||||
((strict (if (= (nth type-name (- (len type-name) 1)) "!") (string-slice type-name 0 (- (len type-name) 1)) nil)))
|
||||
(if
|
||||
strict
|
||||
(list (quote type-check!) left strict)
|
||||
|
||||
@@ -295,7 +295,15 @@
|
||||
|
||||
(define
|
||||
hs-falsy?
|
||||
(fn (v) (or (nil? v) (= v false) (and (string? v) (= v "")))))
|
||||
(fn
|
||||
(v)
|
||||
(cond
|
||||
((nil? v) true)
|
||||
((= v false) true)
|
||||
((and (string? v) (= v "")) true)
|
||||
((and (list? v) (= (len v) 0)) true)
|
||||
((= v 0) true)
|
||||
(true false))))
|
||||
|
||||
(define
|
||||
hs-matches?
|
||||
@@ -313,4 +321,15 @@
|
||||
(cond
|
||||
((list? collection) (some (fn (x) (= x item)) collection))
|
||||
((string? collection) (string-contains? collection item))
|
||||
(true false))))
|
||||
|
||||
(define
|
||||
hs-empty?
|
||||
(fn
|
||||
(v)
|
||||
(cond
|
||||
((nil? v) true)
|
||||
((string? v) (= (len v) 0))
|
||||
((list? v) (= (len v) 0))
|
||||
((dict? v) (= (len (keys v)) 0))
|
||||
(true false))))
|
||||
@@ -152,7 +152,8 @@
|
||||
"includes"
|
||||
"contain"
|
||||
"undefined"
|
||||
"exist"))
|
||||
"exist"
|
||||
"match"))
|
||||
|
||||
(define hs-keyword? (fn (word) (some (fn (k) (= k word)) hs-keywords)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user