From 920bc80042b1f389852fc14aa2788930d9907892 Mon Sep 17 00:00:00 2001 From: Jonathon Leight Date: Thu, 2 Jul 2026 19:20:35 -0400 Subject: [PATCH] Null checks --- internal/web/static/console.js | 5 +++-- internal/web/static/serial-setup.js | 20 +++++++++++++------- internal/web/static/serial.js | 5 +++-- internal/web/static/webauthn.js | 6 ++++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/internal/web/static/console.js b/internal/web/static/console.js index abbcb5d..408eea3 100644 --- a/internal/web/static/console.js +++ b/internal/web/static/console.js @@ -21,8 +21,9 @@ } if (!("serial" in navigator)) { - document.getElementById("unsupported").hidden = false; - connectBtn.disabled = true; + const unsupportedEl = document.getElementById("unsupported"); + if (unsupportedEl) unsupportedEl.hidden = false; + if (connectBtn) connectBtn.disabled = true; return; } diff --git a/internal/web/static/serial-setup.js b/internal/web/static/serial-setup.js index d3670d9..cfa9a9e 100644 --- a/internal/web/static/serial-setup.js +++ b/internal/web/static/serial-setup.js @@ -13,6 +13,12 @@ "use strict"; var $ = function (id) { return document.getElementById(id); }; + // on wires an event handler, skipping silently if the element is absent, so a + // trimmed-down template can omit controls without breaking setup. + var on = function (id, event, fn) { + var el = $(id); + if (el) el.addEventListener(event, fn); + }; var hex = function (bytes) { return Array.prototype.map.call(bytes, function (b) { return b.toString(16).padStart(2, "0"); @@ -339,15 +345,15 @@ document.querySelectorAll('input[name="keymode"]').forEach(function (el) { el.addEventListener("change", refreshKeyMode); }); - $("regen").addEventListener("click", function () { + on("regen", "click", function () { generateKeyPair().then(function (k) { setKeyState(k.privHex, k.pubHex); }); }); - $("privkey").addEventListener("input", function () { + on("privkey", "input", function () { if (selectedKeyMode() === "paste") applyPastedKey(); }); - $("grind").addEventListener("click", grind); - $("grind-stop").addEventListener("click", function () { grinding = false; }); - $("org").addEventListener("change", refreshOrg); - $("generate").addEventListener("click", generate); - $("run").addEventListener("click", run); + on("grind", "click", grind); + on("grind-stop", "click", function () { grinding = false; }); + on("org", "change", refreshOrg); + on("generate", "click", generate); + on("run", "click", run); })(); diff --git a/internal/web/static/serial.js b/internal/web/static/serial.js index db08b35..8e32068 100644 --- a/internal/web/static/serial.js +++ b/internal/web/static/serial.js @@ -18,8 +18,9 @@ } if (!("serial" in navigator)) { - document.getElementById("unsupported").hidden = false; - connectBtn.disabled = true; + const unsupportedEl = document.getElementById("unsupported"); + if (unsupportedEl) unsupportedEl.hidden = false; + if (connectBtn) connectBtn.disabled = true; return; } diff --git a/internal/web/static/webauthn.js b/internal/web/static/webauthn.js index 92decb2..2af396d 100644 --- a/internal/web/static/webauthn.js +++ b/internal/web/static/webauthn.js @@ -80,7 +80,8 @@ async function postJSON(url, body) { } async function passkeyRegister() { - const username = document.getElementById("username").value.trim(); + const nameEl = document.getElementById("username"); + const username = nameEl ? nameEl.value.trim() : ""; const dnEl = document.getElementById("displayName"); const displayName = dnEl ? dnEl.value.trim() : ""; try { @@ -140,7 +141,8 @@ async function addPasskey() { // passkeyLogin runs a username-scoped assertion (for credentials that aren't // discoverable, where the server needs to know which account to challenge). async function passkeyLogin() { - const username = document.getElementById("username").value.trim(); + const nameEl = document.getElementById("username"); + const username = nameEl ? nameEl.value.trim() : ""; try { setStatus("Starting…"); const options = await postJSON("/api/login/begin", { username });