From 3a513aaa5a13881fa79007ec84954d13c70b750a Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Mon, 4 May 2026 11:01:14 -0500 Subject: [PATCH] runtime + codegen-js: Promise helpers and object/array utilities Add to el_runtime.js: promise_then(p, cb) -- p.then(cb), works with any Promise-returning API promise_catch(p, cb) -- p.catch(cb) promise_resolve(val) -- Promise.resolve(val) promise_reject(msg) -- Promise.reject(new Error(msg)) object_assign(t, s) -- Object.assign({}, t, s) (non-mutating) object_keys(obj) -- Object.keys(obj) object_values(obj) -- Object.values(obj) json_deep_clone(obj) -- JSON.parse(JSON.stringify(obj)) array_from(iterable) -- Array.from(iterable) type_of(val) -- typeof val instanceof_check(v, n) -- val instanceof globalThis[name] All new functions added to __el export object and ES named exports. codegen-js preamble destructure updated to include all new names. --- el-compiler/runtime/el_runtime.js | 72 +++++++++++++++++++++++++++++++ el-compiler/src/codegen-js.el | 3 ++ 2 files changed, 75 insertions(+) diff --git a/el-compiler/runtime/el_runtime.js b/el-compiler/runtime/el_runtime.js index 88a16e1..a223fdb 100644 --- a/el-compiler/runtime/el_runtime.js +++ b/el-compiler/runtime/el_runtime.js @@ -766,6 +766,68 @@ function window_get(name) { return null; } +// ── Promise helpers ──────────────────────────────────────────────────────── +// +// Third-party APIs often return Promises but are not El @async functions. +// These helpers let El programs chain .then / .catch without needing +// native_js, and without requiring the callee to be @async. + +function promise_then(p, cb) { + return Promise.resolve(p).then(cb); +} + +function promise_catch(p, cb) { + return Promise.resolve(p).catch(cb); +} + +function promise_resolve(val) { + return Promise.resolve(val); +} + +function promise_reject(msg) { + return Promise.reject(new Error(String(msg))); +} + +// ── Object / Array utilities ─────────────────────────────────────────────── +// +// Structural operations on Any-typed JS values. These complement the +// El map/list primitives for interop with third-party library objects. + +function object_assign(target, source) { + return Object.assign(Object.assign({}, target), source); +} + +function object_keys(obj) { + if (obj === null || obj === undefined) return []; + return Object.keys(obj); +} + +function object_values(obj) { + if (obj === null || obj === undefined) return []; + return Object.values(obj); +} + +function json_deep_clone(obj) { + if (obj === null || obj === undefined) return null; + return JSON.parse(JSON.stringify(obj)); +} + +function array_from(iterable) { + if (iterable === null || iterable === undefined) return []; + return Array.from(iterable); +} + +function type_of(val) { + return typeof val; +} + +function instanceof_check(val, constructor_name) { + if (typeof globalThis[constructor_name] === 'function') { + return val instanceof globalThis[constructor_name]; + } + return false; +} + // ── native_js escape hatch ───────────────────────────────────────────────── // // Evaluate arbitrary JS from El source. Intended for calling third-party @@ -910,6 +972,11 @@ const __el = { console_log, // Window export helpers window_set, window_get, + // Promise helpers + promise_then, promise_catch, promise_resolve, promise_reject, + // Object / Array utilities + object_assign, object_keys, object_values, json_deep_clone, + array_from, type_of, instanceof_check, // native_js escape hatch native_js, native_js_call, // CGI / DHARMA / Engram / LLM (stubs) @@ -974,4 +1041,9 @@ export { console_log, // Window / native_js window_set, window_get, native_js, native_js_call, + // Promise helpers + promise_then, promise_catch, promise_resolve, promise_reject, + // Object / Array utilities + object_assign, object_keys, object_values, json_deep_clone, + array_from, type_of, instanceof_check, }; diff --git a/el-compiler/src/codegen-js.el b/el-compiler/src/codegen-js.el index 7717eaa..f0de87a 100644 --- a/el-compiler/src/codegen-js.el +++ b/el-compiler/src/codegen-js.el @@ -1105,6 +1105,9 @@ fn codegen_js_inner(stmts: [Map], source: String, bundle_mode: Bool js_emit_line(" window_location, window_redirect, window_on_load,") js_emit_line(" console_log,") js_emit_line(" window_set, window_get, native_js, native_js_call,") + js_emit_line(" promise_then, promise_catch, promise_resolve, promise_reject,") + js_emit_line(" object_assign, object_keys, object_values, json_deep_clone,") + js_emit_line(" array_from, type_of, instanceof_check,") js_emit_line("} = globalThis.__el;") js_emit_blank() }