From 6293a0fe70dc2e68ff6c3235cb9878779a851f39 Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 23 Apr 2026 23:34:05 +0000 Subject: [PATCH] js-on-sx: delete operator js-transpile-unop intercepts 'delete' before transpiling the operand. Maps to (js-delete-prop obj key) for members and indexed access. Runtime js-delete-prop sets the dict value to js-undefined and returns true. 444/446 unit (+2), 148/148 slice unchanged. --- lib/js/runtime.sx | 9 +++++++++ lib/js/test.sh | 10 ++++++++++ lib/js/transpile.sx | 35 +++++++++++++++++++++++++---------- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index 5fe9a266..e0bf701b 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -1825,6 +1825,15 @@ (define Object {:entries js-object-entries :values js-object-values :freeze js-object-freeze :assign js-object-assign :keys js-object-keys}) +(define + js-delete-prop + (fn + (obj key) + (cond + ((dict? obj) + (begin (dict-set! obj (js-to-string key) js-undefined) true)) + (else true)))) + (define js-optchain-get (fn diff --git a/lib/js/test.sh b/lib/js/test.sh index 97491cd1..d074c0c4 100755 --- a/lib/js/test.sh +++ b/lib/js/test.sh @@ -1141,6 +1141,12 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 3201) (eval "(js-eval \"var {aa: x2, bb: y2} = {aa:1, bb:2}; x2+y2\")") +;; ── Phase 11.delete ──────────────────────────────────────────── +(epoch 3300) +(eval "(js-eval \"var o = {x: 5}; delete o.x; o.x === undefined\")") +(epoch 3301) +(eval "(js-eval \"var o = {a:1, b:2}; delete o.a; o.b\")") + EPOCHS @@ -1760,6 +1766,10 @@ check 3101 "rest arr join" '"2,3,4"' check 3200 "obj rename" '100' check 3201 "obj multi rename" '3' +# ── Phase 11.delete ─────────────────────────────────────────── +check 3300 "delete obj.x" 'true' +check 3301 "delete obj.a keeps b" '2' + TOTAL=$((PASS + FAIL)) if [ $FAIL -eq 0 ]; then echo "✓ $PASS/$TOTAL JS-on-SX tests passed" diff --git a/lib/js/transpile.sx b/lib/js/transpile.sx index 90aa57d8..3bfe8655 100644 --- a/lib/js/transpile.sx +++ b/lib/js/transpile.sx @@ -165,16 +165,31 @@ js-transpile-unop (fn (op arg) - (let - ((a (js-transpile arg))) - (cond - ((= op "-") (list (js-sym "js-neg") a)) - ((= op "+") (list (js-sym "js-pos") a)) - ((= op "!") (list (js-sym "js-not") a)) - ((= op "~") (list (js-sym "js-bitnot") a)) - ((= op "typeof") (list (js-sym "js-typeof") a)) - ((= op "void") (list (js-sym "quote") :js-undefined)) - (else (error (str "js-transpile-unop: unsupported op: " op))))))) + (cond + ((= op "delete") + (cond + ((js-tag? arg "js-member") + (list + (js-sym "js-delete-prop") + (js-transpile (nth arg 1)) + (nth arg 2))) + ((js-tag? arg "js-index") + (list + (js-sym "js-delete-prop") + (js-transpile (nth arg 1)) + (js-transpile (nth arg 2)))) + (else true))) + (else + (let + ((a (js-transpile arg))) + (cond + ((= op "-") (list (js-sym "js-neg") a)) + ((= op "+") (list (js-sym "js-pos") a)) + ((= op "!") (list (js-sym "js-not") a)) + ((= op "~") (list (js-sym "js-bitnot") a)) + ((= op "typeof") (list (js-sym "js-typeof") a)) + ((= op "void") (list (js-sym "quote") :js-undefined)) + (else (error (str "js-transpile-unop: unsupported op: " op))))))))) ;; ── Binary ops ────────────────────────────────────────────────────