implement ? nil-propagation, write browser-auth.el example, update spec

Iteration 5:

? nil-propagation: Field and Index handlers in js_cg_expr now detect when
the object expression is a Try node (the AST node for postfix `?`).
When detected, emit JS optional chaining: `(expr)?.["field"] ?? null`.
The `?? null` normalizes JS undefined to El's null. A bare `expr?` not
followed by field/index still passes through unchanged.

browser-auth.el: a realistic 130-line example demonstrating:
  - @async function with Supabase via native_js_call
  - DOM bridge: get/set value/text/attr, add/remove class, show/hide
  - local_storage_get/set for session hints
  - window_on_load for initialization
  - window_set to expose functions to the browser global scope
  - set_timeout for transient state, is_valid_email for input validation
  Compiles cleanly with elc --target=js --bundle

Spec updated: status promoted to Phase 4 / ~80% coverage, nil-prop
status updated, new example referenced.
This commit is contained in:
Will Anderson
2026-05-04 10:42:54 -05:00
parent 422442b14e
commit 21694b79d2
4 changed files with 190 additions and 2 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# El JavaScript Backend (codegen-js)
**Status:** Phase 3 complete. Hello-world compiles and runs. ~50% language coverage. Core runtime (~50 builtins) implemented including full DOM bridge, window export helpers, native_js escape hatches, and @async/await support. CGI / DHARMA / LLM / Engram intentionally stubbed.
**Status:** Phase 4 complete. ~80% language coverage. Core runtime (~70 builtins) implemented including full DOM bridge (extended), localStorage, timers, window navigation, window export helpers, native_js escape hatches, and @async/await support. Enum::Variant match patterns fully implemented in parser and both codegens. TypeDef parser bug fixed (= before { consumed correctly). `?` nil-propagation compiles to JS optional chaining for field/index access. `--bundle` flag produces self-contained IIFE output for direct `<script>` use. CGI / DHARMA / LLM / Engram intentionally stubbed.
**Authoritative files**
@@ -212,7 +212,7 @@ This is the canonical list. Programs that use any of these compile (no `#error`-
| `match` expressions | Compiled (basic) | LitInt/LitStr/LitBool/Wildcard/Binding all work via `if/else` chain. Tagged-union match deferred |
| `type` (struct) defs | Skipped at codegen | Treated as documentation; structs are plain JS objects. `t["field"]` works |
| `enum` defs | Skipped at codegen | Same — enum values are bare strings or ints |
| `?` postfix (nil-prop) | No-op | Same as C backend's current state |
| `?` postfix (nil-prop) | Implemented for field/index access | `obj?.field` emits `(obj)?.["field"] ?? null` via JS optional chaining. Bare `expr?` still passes through (no-op). |
| `try` postfix | Stripped to inner | Same as C backend |
| Capability enforcement | Not enforced | The C backend uses `#error` directives; the JS backend lets the runtime stubs throw. Future: emit `throw new Error('capability violation')` at compile time |
| VBD role check | Not enforced | Same |