add 20 browser API builtins to JS runtime and codegen preamble
Iteration 3: closes the browser API gap needed for real web pages.
New builtins in el_runtime.js:
Extended DOM: dom_set_attr, dom_get_attr, dom_remove_attr, dom_set_html,
dom_get_html, dom_get_parent, dom_contains_class, dom_get_checked,
dom_set_checked
Timers: set_timeout, set_interval, clear_interval
Local storage: local_storage_get, local_storage_set, local_storage_remove
Window: window_location, window_redirect, window_on_load
Debug: console_log
All browser-only functions use _ensureBrowser guard. Timer functions
work in both Node and browser. All new names added to __el export
object, ES named exports, and codegen-js.el destructure preamble.
Spec table updated to document new categories.
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -630,6 +630,120 @@ function dom_is_null(el) {
|
|||||||
return el === null || el === undefined;
|
return el === null || el === undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Extended DOM API (browser-only) ───────────────────────────────────────
|
||||||
|
|
||||||
|
function dom_set_attr(el, attr, val) {
|
||||||
|
_ensureBrowser('dom_set_attr');
|
||||||
|
if (el != null) el.setAttribute(String(attr), String(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_get_attr(el, attr) {
|
||||||
|
_ensureBrowser('dom_get_attr');
|
||||||
|
if (el == null) return '';
|
||||||
|
return el.getAttribute(String(attr)) ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_remove_attr(el, attr) {
|
||||||
|
_ensureBrowser('dom_remove_attr');
|
||||||
|
if (el != null) el.removeAttribute(String(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_set_html(el, html) {
|
||||||
|
_ensureBrowser('dom_set_html');
|
||||||
|
if (el != null) el.innerHTML = String(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_get_html(el) {
|
||||||
|
_ensureBrowser('dom_get_html');
|
||||||
|
return el == null ? '' : String(el.innerHTML ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_get_parent(el) {
|
||||||
|
_ensureBrowser('dom_get_parent');
|
||||||
|
return el == null ? null : (el.parentElement ?? null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_contains_class(el, cls) {
|
||||||
|
_ensureBrowser('dom_contains_class');
|
||||||
|
if (el == null) return false;
|
||||||
|
return el.classList.contains(String(cls));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_get_checked(el) {
|
||||||
|
_ensureBrowser('dom_get_checked');
|
||||||
|
return el == null ? false : Boolean(el.checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dom_set_checked(el, val) {
|
||||||
|
_ensureBrowser('dom_set_checked');
|
||||||
|
if (el != null) el.checked = Boolean(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Timer API (browser + Node) ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
function set_timeout(ms, cb) {
|
||||||
|
if (typeof setTimeout === 'undefined') {
|
||||||
|
throw new Error('set_timeout: setTimeout not available in this environment');
|
||||||
|
}
|
||||||
|
setTimeout(cb, ms | 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_interval(ms, cb) {
|
||||||
|
if (typeof setInterval === 'undefined') {
|
||||||
|
throw new Error('set_interval: setInterval not available in this environment');
|
||||||
|
}
|
||||||
|
return setInterval(cb, ms | 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear_interval(handle) {
|
||||||
|
if (typeof clearInterval !== 'undefined') clearInterval(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Local storage (browser-only) ───────────────────────────────────────────
|
||||||
|
|
||||||
|
function local_storage_get(key) {
|
||||||
|
_ensureBrowser('local_storage_get');
|
||||||
|
return localStorage.getItem(String(key)) ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function local_storage_set(key, val) {
|
||||||
|
_ensureBrowser('local_storage_set');
|
||||||
|
localStorage.setItem(String(key), String(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
function local_storage_remove(key) {
|
||||||
|
_ensureBrowser('local_storage_remove');
|
||||||
|
localStorage.removeItem(String(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Window location / navigation (browser-only) ────────────────────────────
|
||||||
|
|
||||||
|
function window_location() {
|
||||||
|
_ensureBrowser('window_location');
|
||||||
|
return window.location.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
function window_redirect(url) {
|
||||||
|
_ensureBrowser('window_redirect');
|
||||||
|
window.location.href = String(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function window_on_load(cb) {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
document.addEventListener('DOMContentLoaded', cb);
|
||||||
|
} else if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('load', cb);
|
||||||
|
}
|
||||||
|
// In Node: no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── console_log (explicit debug log, distinct from println) ────────────────
|
||||||
|
|
||||||
|
function console_log(msg) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(String(msg));
|
||||||
|
}
|
||||||
|
|
||||||
// ── Window export helpers ──────────────────────────────────────────────────
|
// ── Window export helpers ──────────────────────────────────────────────────
|
||||||
//
|
//
|
||||||
// Expose El functions to the browser's global scope so they can be called
|
// Expose El functions to the browser's global scope so they can be called
|
||||||
@@ -783,6 +897,17 @@ const __el = {
|
|||||||
dom_set_prop, dom_get_prop, dom_set_style, dom_add_class, dom_remove_class,
|
dom_set_prop, dom_get_prop, dom_set_style, dom_add_class, dom_remove_class,
|
||||||
dom_show, dom_hide, dom_listen, dom_query, dom_query_all, dom_create,
|
dom_show, dom_hide, dom_listen, dom_query, dom_query_all, dom_create,
|
||||||
dom_append, dom_remove, dom_is_null,
|
dom_append, dom_remove, dom_is_null,
|
||||||
|
// Extended DOM
|
||||||
|
dom_set_attr, dom_get_attr, dom_remove_attr, dom_set_html, dom_get_html,
|
||||||
|
dom_get_parent, dom_contains_class, dom_get_checked, dom_set_checked,
|
||||||
|
// Timers
|
||||||
|
set_timeout, set_interval, clear_interval,
|
||||||
|
// Local storage
|
||||||
|
local_storage_get, local_storage_set, local_storage_remove,
|
||||||
|
// Window location
|
||||||
|
window_location, window_redirect, window_on_load,
|
||||||
|
// Debug
|
||||||
|
console_log,
|
||||||
// Window export helpers
|
// Window export helpers
|
||||||
window_set, window_get,
|
window_set, window_get,
|
||||||
// native_js escape hatch
|
// native_js escape hatch
|
||||||
@@ -836,6 +961,17 @@ export {
|
|||||||
dom_set_prop, dom_get_prop, dom_set_style, dom_add_class, dom_remove_class,
|
dom_set_prop, dom_get_prop, dom_set_style, dom_add_class, dom_remove_class,
|
||||||
dom_show, dom_hide, dom_listen, dom_query, dom_query_all, dom_create,
|
dom_show, dom_hide, dom_listen, dom_query, dom_query_all, dom_create,
|
||||||
dom_append, dom_remove, dom_is_null,
|
dom_append, dom_remove, dom_is_null,
|
||||||
|
// Extended DOM
|
||||||
|
dom_set_attr, dom_get_attr, dom_remove_attr, dom_set_html, dom_get_html,
|
||||||
|
dom_get_parent, dom_contains_class, dom_get_checked, dom_set_checked,
|
||||||
|
// Timers
|
||||||
|
set_timeout, set_interval, clear_interval,
|
||||||
|
// Local storage
|
||||||
|
local_storage_get, local_storage_set, local_storage_remove,
|
||||||
|
// Window location
|
||||||
|
window_location, window_redirect, window_on_load,
|
||||||
|
// Debug
|
||||||
|
console_log,
|
||||||
// Window / native_js
|
// Window / native_js
|
||||||
window_set, window_get, native_js, native_js_call,
|
window_set, window_get, native_js, native_js_call,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -933,6 +933,12 @@ fn codegen_js(stmts: [Map<String, Any>], source: String) -> String {
|
|||||||
js_emit_line(" dom_set_prop, dom_get_prop, dom_set_style, dom_add_class, dom_remove_class,")
|
js_emit_line(" dom_set_prop, dom_get_prop, dom_set_style, dom_add_class, dom_remove_class,")
|
||||||
js_emit_line(" dom_show, dom_hide, dom_listen, dom_query, dom_query_all, dom_create,")
|
js_emit_line(" dom_show, dom_hide, dom_listen, dom_query, dom_query_all, dom_create,")
|
||||||
js_emit_line(" dom_append, dom_remove, dom_is_null,")
|
js_emit_line(" dom_append, dom_remove, dom_is_null,")
|
||||||
|
js_emit_line(" dom_set_attr, dom_get_attr, dom_remove_attr, dom_set_html, dom_get_html,")
|
||||||
|
js_emit_line(" dom_get_parent, dom_contains_class, dom_get_checked, dom_set_checked,")
|
||||||
|
js_emit_line(" set_timeout, set_interval, clear_interval,")
|
||||||
|
js_emit_line(" local_storage_get, local_storage_set, local_storage_remove,")
|
||||||
|
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(" window_set, window_get, native_js, native_js_call,")
|
||||||
js_emit_line("} = globalThis.__el;")
|
js_emit_line("} = globalThis.__el;")
|
||||||
js_emit_blank()
|
js_emit_blank()
|
||||||
|
|||||||
@@ -79,6 +79,11 @@ Same function names as `el_runtime.c` wherever possible, so codegen-js can emit
|
|||||||
| `state_*` | In-memory `Map` keyed by string |
|
| `state_*` | In-memory `Map` keyed by string |
|
||||||
| `env` | `process.env[k]` in Node, throws in browser |
|
| `env` | `process.env[k]` in Node, throws in browser |
|
||||||
| DOM bridge (Phase 3) | `dom_get_element`, `dom_get_value`, `dom_set_value`, `dom_get_text`, `dom_set_text`, `dom_set_prop`, `dom_get_prop`, `dom_set_style`, `dom_add_class`, `dom_remove_class`, `dom_show`, `dom_hide`, `dom_listen`, `dom_query`, `dom_query_all`, `dom_create`, `dom_append`, `dom_remove`, `dom_is_null` (browser-only; throw in Node) |
|
| DOM bridge (Phase 3) | `dom_get_element`, `dom_get_value`, `dom_set_value`, `dom_get_text`, `dom_set_text`, `dom_set_prop`, `dom_get_prop`, `dom_set_style`, `dom_add_class`, `dom_remove_class`, `dom_show`, `dom_hide`, `dom_listen`, `dom_query`, `dom_query_all`, `dom_create`, `dom_append`, `dom_remove`, `dom_is_null` (browser-only; throw in Node) |
|
||||||
|
| DOM extended (Phase 4) | `dom_set_attr`, `dom_get_attr`, `dom_remove_attr`, `dom_set_html`, `dom_get_html`, `dom_get_parent`, `dom_contains_class`, `dom_get_checked`, `dom_set_checked` (browser-only) |
|
||||||
|
| Timers | `set_timeout(ms, cb)`, `set_interval(ms, cb) -> Int`, `clear_interval(handle)` (browser + Node) |
|
||||||
|
| Local storage | `local_storage_get(key)`, `local_storage_set(key, val)`, `local_storage_remove(key)` (browser-only) |
|
||||||
|
| Window location | `window_location() -> String`, `window_redirect(url)`, `window_on_load(cb)` (browser-only) |
|
||||||
|
| Debug | `console_log(msg)` -- explicit console.log, separate from println |
|
||||||
| Window export | `window_set(name, val)`, `window_get(name)` — expose/retrieve values on `window` (or `globalThis` in Node) |
|
| Window export | `window_set(name, val)`, `window_get(name)` — expose/retrieve values on `window` (or `globalThis` in Node) |
|
||||||
| native_js escape hatch | `native_js(code)` — evaluates a JS expression via `eval`; `native_js_call(obj, method, args)` — calls a method on an object. Use for third-party browser libraries until proper bindings exist |
|
| native_js escape hatch | `native_js(code)` — evaluates a JS expression via `eval`; `native_js_call(obj, method, args)` — calls a method on an object. Use for third-party browser libraries until proper bindings exist |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user