Editor: add console breadcrumbs to updateFirmware to diagnose a silent no-op

User reports the updater does nothing with no visible error. Every code path shows a
dialog, so it's bailing before/at one of them (likely browser dialog-suppression making
confirm() return false, a stale/cached editor, or an uncaught throw). Log each step so a
console trace pinpoints where it stops.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Me Here 2026-05-29 15:00:56 -05:00
parent 73d18ab1f3
commit c5cc329185

View file

@ -1201,9 +1201,14 @@ function _queryDeviceVersion() { // ask the device its firmware version (SysEx
return new Promise((res) => { _verCb = res; _send([0xF0, 0x7D, 0x02, 0xF7]); setTimeout(() => { if (_verCb) { _verCb = null; res(null); } }, 1500); }); return new Promise((res) => { _verCb = res; _send([0xF0, 0x7D, 0x02, 0xF7]); setTimeout(() => { if (_verCb) { _verCb = null; res(null); } }, 1500); });
} }
async function updateFirmware() { // A/B firmware update over USB-MIDI: push the precompiled .mpy async function updateFirmware() { // A/B firmware update over USB-MIDI: push the precompiled .mpy
if (!(await _ensureMidi()) || !_midiOutputs().length) console.log("[fw] update start");
if (!(await _ensureMidi()) || !_midiOutputs().length) {
console.log("[fw] no MIDI output (outputs:", _midiOutputs().length, ")");
return alert("Connect the PM_K-1 (Chrome/Edge/Firefox), then try again."); return alert("Connect the PM_K-1 (Chrome/Edge/Firefox), then try again.");
}
console.log("[fw] MIDI ok; outputs:", _midiOutputs().map((o) => o.name));
const dev = await _queryDeviceVersion(); const dev = await _queryDeviceVersion();
console.log("[fw] device version reply:", dev);
let latest = null, b64 = null; let latest = null, b64 = null;
// version comes from the (text) source; the payload is the precompiled .mpy bytecode — CircuitPython // version comes from the (text) source; the payload is the precompiled .mpy bytecode — CircuitPython
// compiles a big .py at boot, which OOMs the RP2040, so we ship + push compiled bytecode instead. // compiles a big .py at boot, which OOMs the RP2040, so we ship + push compiled bytecode instead.
@ -1220,11 +1225,17 @@ async function updateFirmware() { // A/B firmware update over USB-MIDI: push t
b64 = _b64(u8); if (!latest) latest = "(picked .mpy)"; b64 = _b64(u8); if (!latest) latest = "(picked .mpy)";
} }
if (!latest) latest = "?"; if (!latest) latest = "?";
console.log("[fw] latest:", latest, "| .mpy base64 length:", b64 && b64.length);
const upToDate = dev && dev === latest; const upToDate = dev && dev === latest;
if (!confirm("Device firmware: " + (dev || "unknown") + "\nNew build: " + latest + if (!confirm("Device firmware: " + (dev || "unknown") + "\nNew build: " + latest +
(upToDate ? "\n\nSame version. Re-install anyway?" (upToDate ? "\n\nSame version. Re-install anyway?"
: "\n\nUpdate now? The device reboots, runs the new build, and auto-rolls-back if it fails to start."))) return; : "\n\nUpdate now? The device reboots, runs the new build, and auto-rolls-back if it fails to start."))) {
console.log("[fw] confirm returned false (cancelled, OR the browser is suppressing dialogs -> reload the page)");
return;
}
console.log("[fw] pushing", b64.length, "base64 chars...");
const err = await _pushFirmware(b64); const err = await _pushFirmware(b64);
console.log("[fw] push result:", err || "OK");
if (err) return alert("Update didn't complete (" + err + ").\n\nThe device kept its working firmware — nothing was installed. " + if (err) return alert("Update didn't complete (" + err + ").\n\nThe device kept its working firmware — nothing was installed. " +
"Make sure it's plugged in and NOT in editor mode (don't hold A), then retry."); "Make sure it's plugged in and NOT in editor mode (don't hold A), then retry.");
alert("Update sent ✓ — the device verified v" + latest + " and is rebooting into it. It auto-confirms after a few seconds, or rolls back if it won't start."); alert("Update sent ✓ — the device verified v" + latest + " and is rebooting into it. It auto-confirms after a few seconds, or rolls back if it won't start.");