js-on-sx: optional chaining ?.

Parser: jp-parse-postfix handles op "?." followed by ident / [ / (
emitting (js-optchain-member obj name), (js-optchain-index obj k),
or (js-optchain-call callee args).

Transpile: each emits (js-optchain-get obj key) or (js-optchain-call
fn args).

Runtime: js-optchain-get and js-optchain-call short-circuit to
js-undefined when receiver is null/undefined.

423/425 unit (+5), 148/148 slice unchanged.
This commit is contained in:
2026-04-23 22:38:45 +00:00
parent 067c0ab34a
commit 18ae63b0bd
4 changed files with 103 additions and 0 deletions

View File

@@ -593,6 +593,42 @@
(jp-call-args-loop st args)
(jp-expect! st "punct" ")")
(jp-parse-postfix st (list (quote js-call) left args)))))
((jp-at? st "op" "?.")
(do
(jp-advance! st)
(cond
((jp-at? st "punct" "[")
(begin
(jp-advance! st)
(let
((k (jp-parse-assignment st)))
(jp-expect! st "punct" "]")
(jp-parse-postfix
st
(list (quote js-optchain-index) left k)))))
((jp-at? st "punct" "(")
(begin
(jp-advance! st)
(let
((args (list)))
(jp-call-args-loop st args)
(jp-expect! st "punct" ")")
(jp-parse-postfix
st
(list (quote js-optchain-call) left args)))))
(else
(let
((t (jp-peek st)))
(if
(or
(= (get t :type) "ident")
(= (get t :type) "keyword"))
(do
(jp-advance! st)
(jp-parse-postfix
st
(list (quote js-optchain-member) left (get t :value))))
(error "expected ident, [ or ( after ?.")))))))
((or (jp-at? st "op" "++") (jp-at? st "op" "--"))
(let
((op (get (jp-peek st) :value)))