diff --git a/lib/hyperscript/compiler.sx b/lib/hyperscript/compiler.sx index eafb94fe..3374d412 100644 --- a/lib/hyperscript/compiler.sx +++ b/lib/hyperscript/compiler.sx @@ -166,13 +166,14 @@ finally-info having-info of-filter-info - count-filter-info) + count-filter-info + elsewhere?) (cond ((<= (len items) 1) (let ((body (if (> (len items) 0) (first items) nil))) (let - ((target (if source (hs-to-sx source) (quote me)))) + ((target (cond (elsewhere? (list (quote dom-body))) (source (hs-to-sx source)) (true (quote me))))) (let ((event-refs (if (and (list? body) (= (first body) (quote do))) (filter (fn (x) (and (list? x) (= (first x) (quote ref)))) (rest body)) (list)))) (let @@ -180,7 +181,7 @@ (let ((raw-compiled (hs-to-sx stripped-body))) (let - ((compiled-body (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote host-get) (list (quote host-get) (quote event) "detail") name)))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) + ((compiled-body (let ((base (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote host-get) (list (quote host-get) (quote event) "detail") name)))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) (if elsewhere? (list (quote when) (list (quote not) (list (quote host-call) (quote me) "contains" (list (quote host-get) (quote event) "target"))) base) base)))) (let ((wrapped-body (if catch-info (let ((var (make-symbol (nth catch-info 0))) (catch-body (hs-to-sx (nth catch-info 1)))) (if finally-info (list (quote do) (list (quote guard) (list var (list true catch-body)) compiled-body) (hs-to-sx finally-info)) (list (quote guard) (list var (list true catch-body)) compiled-body))) (if finally-info (list (quote do) compiled-body (hs-to-sx finally-info)) compiled-body)))) (let @@ -235,7 +236,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :filter) (scan-on (rest (rest items)) @@ -246,7 +248,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :every) (scan-on (rest (rest items)) @@ -257,7 +260,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :catch) (scan-on (rest (rest items)) @@ -268,7 +272,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :finally) (scan-on (rest (rest items)) @@ -279,7 +284,8 @@ (nth items 1) having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :having) (scan-on (rest (rest items)) @@ -290,7 +296,8 @@ finally-info (nth items 1) of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :of-filter) (scan-on (rest (rest items)) @@ -301,7 +308,8 @@ finally-info having-info (nth items 1) - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :count-filter) (scan-on (rest (rest items)) @@ -312,6 +320,19 @@ finally-info having-info of-filter-info + (nth items 1) + elsewhere?)) + ((= (first items) :elsewhere) + (scan-on + (rest (rest items)) + source + filter + every? + catch-info + finally-info + having-info + of-filter-info + count-filter-info (nth items 1))) (true (scan-on @@ -323,8 +344,9 @@ finally-info having-info of-filter-info - count-filter-info))))) - (scan-on (rest parts) nil nil false nil nil nil nil nil))))) + count-filter-info + elsewhere?))))) + (scan-on (rest parts) nil nil false nil nil nil nil nil false))))) (define emit-send (fn diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index ee9682be..b0d6fcf1 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -2611,7 +2611,8 @@ (let ((flt (if (= (tp-type) "bracket-open") (do (adv!) (let ((f (parse-expr))) (if (= (tp-type) "bracket-close") (adv!) nil) f)) nil))) (let - ((source (if (match-kw "from") (parse-expr) nil))) + ((elsewhere? (cond ((match-kw "elsewhere") true) ((and (= (tp-type) "keyword") (= (tp-val) "from") (let ((nxt (if (< (+ p 1) tok-len) (nth tokens (+ p 1)) nil))) (and nxt (= (get nxt "type") "keyword") (= (get nxt "value") "elsewhere")))) (do (adv!) (adv!) true)) (true false))) + (source (if (match-kw "from") (parse-expr) nil))) (let ((h-margin nil) (h-threshold nil)) (define @@ -2655,20 +2656,22 @@ (let ((parts (if flt (append parts (list :filter flt)) parts))) (let - ((parts (if source (append parts (list :from source)) parts))) + ((parts (if elsewhere? (append parts (list :elsewhere true)) parts))) (let - ((parts (if count-filter (append parts (list :count-filter count-filter)) parts))) + ((parts (if source (append parts (list :from source)) parts))) (let - ((parts (if of-filter (append parts (list :of-filter of-filter)) parts))) + ((parts (if count-filter (append parts (list :count-filter count-filter)) parts))) (let - ((parts (if having (append parts (list :having having)) parts))) + ((parts (if of-filter (append parts (list :of-filter of-filter)) parts))) (let - ((parts (if catch-clause (append parts (list :catch catch-clause)) parts))) + ((parts (if having (append parts (list :having having)) parts))) (let - ((parts (if finally-clause (append parts (list :finally finally-clause)) parts))) + ((parts (if catch-clause (append parts (list :catch catch-clause)) parts))) (let - ((parts (append parts (list body)))) - parts)))))))))))))))))))))) + ((parts (if finally-clause (append parts (list :finally finally-clause)) parts))) + (let + ((parts (append parts (list body)))) + parts))))))))))))))))))))))) (define parse-init-feat (fn diff --git a/shared/static/wasm/sx/hs-compiler.sx b/shared/static/wasm/sx/hs-compiler.sx index eafb94fe..3374d412 100644 --- a/shared/static/wasm/sx/hs-compiler.sx +++ b/shared/static/wasm/sx/hs-compiler.sx @@ -166,13 +166,14 @@ finally-info having-info of-filter-info - count-filter-info) + count-filter-info + elsewhere?) (cond ((<= (len items) 1) (let ((body (if (> (len items) 0) (first items) nil))) (let - ((target (if source (hs-to-sx source) (quote me)))) + ((target (cond (elsewhere? (list (quote dom-body))) (source (hs-to-sx source)) (true (quote me))))) (let ((event-refs (if (and (list? body) (= (first body) (quote do))) (filter (fn (x) (and (list? x) (= (first x) (quote ref)))) (rest body)) (list)))) (let @@ -180,7 +181,7 @@ (let ((raw-compiled (hs-to-sx stripped-body))) (let - ((compiled-body (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote host-get) (list (quote host-get) (quote event) "detail") name)))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) + ((compiled-body (let ((base (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote host-get) (list (quote host-get) (quote event) "detail") name)))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) (if elsewhere? (list (quote when) (list (quote not) (list (quote host-call) (quote me) "contains" (list (quote host-get) (quote event) "target"))) base) base)))) (let ((wrapped-body (if catch-info (let ((var (make-symbol (nth catch-info 0))) (catch-body (hs-to-sx (nth catch-info 1)))) (if finally-info (list (quote do) (list (quote guard) (list var (list true catch-body)) compiled-body) (hs-to-sx finally-info)) (list (quote guard) (list var (list true catch-body)) compiled-body))) (if finally-info (list (quote do) compiled-body (hs-to-sx finally-info)) compiled-body)))) (let @@ -235,7 +236,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :filter) (scan-on (rest (rest items)) @@ -246,7 +248,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :every) (scan-on (rest (rest items)) @@ -257,7 +260,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :catch) (scan-on (rest (rest items)) @@ -268,7 +272,8 @@ finally-info having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :finally) (scan-on (rest (rest items)) @@ -279,7 +284,8 @@ (nth items 1) having-info of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :having) (scan-on (rest (rest items)) @@ -290,7 +296,8 @@ finally-info (nth items 1) of-filter-info - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :of-filter) (scan-on (rest (rest items)) @@ -301,7 +308,8 @@ finally-info having-info (nth items 1) - count-filter-info)) + count-filter-info + elsewhere?)) ((= (first items) :count-filter) (scan-on (rest (rest items)) @@ -312,6 +320,19 @@ finally-info having-info of-filter-info + (nth items 1) + elsewhere?)) + ((= (first items) :elsewhere) + (scan-on + (rest (rest items)) + source + filter + every? + catch-info + finally-info + having-info + of-filter-info + count-filter-info (nth items 1))) (true (scan-on @@ -323,8 +344,9 @@ finally-info having-info of-filter-info - count-filter-info))))) - (scan-on (rest parts) nil nil false nil nil nil nil nil))))) + count-filter-info + elsewhere?))))) + (scan-on (rest parts) nil nil false nil nil nil nil nil false))))) (define emit-send (fn diff --git a/shared/static/wasm/sx/hs-parser.sx b/shared/static/wasm/sx/hs-parser.sx index ee9682be..b0d6fcf1 100644 --- a/shared/static/wasm/sx/hs-parser.sx +++ b/shared/static/wasm/sx/hs-parser.sx @@ -2611,7 +2611,8 @@ (let ((flt (if (= (tp-type) "bracket-open") (do (adv!) (let ((f (parse-expr))) (if (= (tp-type) "bracket-close") (adv!) nil) f)) nil))) (let - ((source (if (match-kw "from") (parse-expr) nil))) + ((elsewhere? (cond ((match-kw "elsewhere") true) ((and (= (tp-type) "keyword") (= (tp-val) "from") (let ((nxt (if (< (+ p 1) tok-len) (nth tokens (+ p 1)) nil))) (and nxt (= (get nxt "type") "keyword") (= (get nxt "value") "elsewhere")))) (do (adv!) (adv!) true)) (true false))) + (source (if (match-kw "from") (parse-expr) nil))) (let ((h-margin nil) (h-threshold nil)) (define @@ -2655,20 +2656,22 @@ (let ((parts (if flt (append parts (list :filter flt)) parts))) (let - ((parts (if source (append parts (list :from source)) parts))) + ((parts (if elsewhere? (append parts (list :elsewhere true)) parts))) (let - ((parts (if count-filter (append parts (list :count-filter count-filter)) parts))) + ((parts (if source (append parts (list :from source)) parts))) (let - ((parts (if of-filter (append parts (list :of-filter of-filter)) parts))) + ((parts (if count-filter (append parts (list :count-filter count-filter)) parts))) (let - ((parts (if having (append parts (list :having having)) parts))) + ((parts (if of-filter (append parts (list :of-filter of-filter)) parts))) (let - ((parts (if catch-clause (append parts (list :catch catch-clause)) parts))) + ((parts (if having (append parts (list :having having)) parts))) (let - ((parts (if finally-clause (append parts (list :finally finally-clause)) parts))) + ((parts (if catch-clause (append parts (list :catch catch-clause)) parts))) (let - ((parts (append parts (list body)))) - parts)))))))))))))))))))))) + ((parts (if finally-clause (append parts (list :finally finally-clause)) parts))) + (let + ((parts (append parts (list body)))) + parts))))))))))))))))))))))) (define parse-init-feat (fn diff --git a/spec/tests/test-hyperscript-behavioral.sx b/spec/tests/test-hyperscript-behavioral.sx index d211dcf2..7c3b0b7a 100644 --- a/spec/tests/test-hyperscript-behavioral.sx +++ b/spec/tests/test-hyperscript-behavioral.sx @@ -9197,9 +9197,19 @@ (deftest "rethrown exceptions trigger 'exception' event" (error "SKIP (skip-list): rethrown exceptions trigger 'exception' event")) (deftest "supports \"elsewhere\" modifier" - (error "SKIP (skip-list): supports 'elsewhere' modifier")) + (hs-cleanup!) + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click elsewhere add .clicked") + (dom-append (dom-body) _el-div) + (hs-activate! _el-div) + )) (deftest "supports \"from elsewhere\" modifier" - (error "SKIP (skip-list): supports 'from elsewhere' modifier")) + (hs-cleanup!) + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click from elsewhere add .clicked") + (dom-append (dom-body) _el-div) + (hs-activate! _el-div) + )) (deftest "throttled at