diff --git a/lib/hyperscript/compiler.sx b/lib/hyperscript/compiler.sx index 80fbbf20..6f346d29 100644 --- a/lib/hyperscript/compiler.sx +++ b/lib/hyperscript/compiler.sx @@ -1257,13 +1257,12 @@ ((= head (quote empty-target)) (let ((tgt (nth ast 1))) - (if - (and (list? tgt) (= (first tgt) (quote local))) - (list - (quote set!) - (make-symbol (nth tgt 1)) - (list (quote hs-empty-like) (make-symbol (nth tgt 1)))) - (list (quote hs-empty-target!) (hs-to-sx tgt))))) + (cond + ((and (list? tgt) (= (first tgt) (quote local))) + (emit-set + tgt + (list (quote hs-empty-like) (hs-to-sx tgt)))) + (true (list (quote hs-empty-target!) (hs-to-sx tgt)))))) ((= head (quote open-element)) (list (quote hs-open!) (hs-to-sx (nth ast 1)))) ((= head (quote close-element)) diff --git a/shared/static/wasm/sx/hs-compiler.sx b/shared/static/wasm/sx/hs-compiler.sx index 80fbbf20..6f346d29 100644 --- a/shared/static/wasm/sx/hs-compiler.sx +++ b/shared/static/wasm/sx/hs-compiler.sx @@ -1257,13 +1257,12 @@ ((= head (quote empty-target)) (let ((tgt (nth ast 1))) - (if - (and (list? tgt) (= (first tgt) (quote local))) - (list - (quote set!) - (make-symbol (nth tgt 1)) - (list (quote hs-empty-like) (make-symbol (nth tgt 1)))) - (list (quote hs-empty-target!) (hs-to-sx tgt))))) + (cond + ((and (list? tgt) (= (first tgt) (quote local))) + (emit-set + tgt + (list (quote hs-empty-like) (hs-to-sx tgt)))) + (true (list (quote hs-empty-target!) (hs-to-sx tgt)))))) ((= head (quote open-element)) (list (quote hs-open!) (hs-to-sx (nth ast 1)))) ((= head (quote close-element)) diff --git a/tests/hs-run-filtered.js b/tests/hs-run-filtered.js index 93a8992d..8e122561 100755 --- a/tests/hs-run-filtered.js +++ b/tests/hs-run-filtered.js @@ -265,7 +265,18 @@ const _log = _origLog; // keep reference for our own output // ─── FFI ──────────────────────────────────────────────────────── K.registerNative('host-global',a=>{const n=a[0];return(n in globalThis)?globalThis[n]:null;}); -K.registerNative('host-get',a=>{if(a[0]==null)return null;let v=a[0][a[1]];if(v===undefined)return null;if((a[1]==='innerHTML'||a[1]==='textContent'||a[1]==='value'||a[1]==='className')&&typeof v!=='string')v=String(v!=null?v:'');return v;}); +K.registerNative('host-get',a=>{ + if(a[0]==null)return null; + // SX lists (arrive as {_type:'list', items:[...]}) don't expose length/size + // through JS property access. Hand-roll common collection queries so + // compiled HS `x.length` / `x.size` works on scoped lists. + if(a[0] && a[0]._type==='list' && (a[1]==='length' || a[1]==='size')) return a[0].items.length; + if(a[0] && a[0]._type==='dict' && a[1]==='size') return Object.keys(a[0]).filter(k=>k!=='_type').length; + let v=a[0][a[1]]; + if(v===undefined)return null; + if((a[1]==='innerHTML'||a[1]==='textContent'||a[1]==='value'||a[1]==='className')&&typeof v!=='string')v=String(v!=null?v:''); + return v; +}); K.registerNative('host-set!',a=>{if(a[0]!=null){const v=a[2]; if(a[1]==='innerHTML'&&a[0] instanceof El){const s=String(v!=null?v:'');a[0]._setInnerHTML(s);a[0][a[1]]=a[0].innerHTML;} else if(a[1]==='textContent'&&a[0] instanceof El){const s=String(v!=null?v:'');a[0].textContent=s;a[0].innerHTML=s;for(const c of a[0].children){c.parentElement=null;c.parentNode=null;}a[0].children=[];a[0].childNodes=[];} else{a[0][a[1]]=v;}} return a[2];}); K.registerNative('host-call',a=>{if(_testDeadline&&Date.now()>_testDeadline)throw new Error('TIMEOUT: wall clock exceeded');const[o,m,...r]=a;if(o==null){const f=globalThis[m];return typeof f==='function'?f.apply(null,r):null;}if(o&&typeof o[m]==='function'){try{const v=o[m].apply(o,r);return v===undefined?null:v;}catch(e){return null;}}return null;}); K.registerNative('host-new',a=>{const C=typeof a[0]==='string'?globalThis[a[0]]:a[0];return typeof C==='function'?new C(...a.slice(1)):null;});