mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-23 05:21:24 +00:00
## Summary Fixes #538 — `null is not an object (evaluating 'pathHops.length')` crash on ADVERT packet detail. ## Root Cause `getParsedPath` caches its result as `p._parsedPath`. If another code path (e.g., object spread, API response) sets `_parsedPath = null`, the cache check (`!== undefined`) passes and returns `null` — causing `.length` to crash. Same pattern exists for `getParsedDecoded`. ## Changes ### `public/packet-helpers.js` - `getParsedPath`: cached return now uses `|| []` to guard against null cache - `getParsedDecoded`: cached return now uses `|| {}` to guard against null cache ### `public/packets.js` - `renderDetail()` (line ~1440): defensive `|| []` / `|| {}` on getParsedPath/getParsedDecoded calls - `buildFlatRowHtml()` (line ~1103): same defensive guards ### `test-frontend-helpers.js` - Added test: cached `_parsedPath = null` returns `[]` - Added test: cached `_parsedDecoded = null` returns `{}` ## Testing All 428 frontend helper tests pass. All 62 packet filter tests pass. Co-authored-by: you <you@example.com>
This commit is contained in:
1 parent
bf8c9e72ec
commit
03e384bbc4
3 files changed
+16
-6
No files matched your search
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
window.getParsedPath = function getParsedPath(p) {
|
||||
if (p._parsedPath !== undefined) return p._parsedPath;
|
||||
if (p._parsedPath !== undefined) return p._parsedPath || [];
|
||||
var raw = p.path_json;
|
||||
if (typeof raw !== 'string') {
|
||||
p._parsedPath = Array.isArray(raw) ? raw : [];
|
||||
@@ -32,7 +32,7 @@ window.clearParsedCache = function clearParsedCache(p) {
|
||||
};
|
||||
|
||||
window.getParsedDecoded = function getParsedDecoded(p) {
|
||||
if (p._parsedDecoded !== undefined) return p._parsedDecoded;
|
||||
if (p._parsedDecoded !== undefined) return p._parsedDecoded || {};
|
||||
var raw = p.decoded_json;
|
||||
if (typeof raw !== 'string') {
|
||||
p._parsedDecoded = (raw && typeof raw === 'object') ? raw : {};
|
||||
|
||||
+4
-4
@@ -1100,8 +1100,8 @@
|
||||
|
||||
// Build HTML for a single flat (ungrouped) packet row
|
||||
function buildFlatRowHtml(p) {
|
||||
const decoded = getParsedDecoded(p);
|
||||
const pathHops = getParsedPath(p);
|
||||
const decoded = getParsedDecoded(p) || {};
|
||||
const pathHops = getParsedPath(p) || [];
|
||||
const region = p.observer_id ? (observerMap.get(p.observer_id)?.iata || '') : '';
|
||||
const typeName = payloadTypeName(p.payload_type);
|
||||
const typeClass = payloadTypeColor(p.payload_type);
|
||||
@@ -1441,8 +1441,8 @@
|
||||
const pkt = data.packet;
|
||||
const breakdown = data.breakdown || {};
|
||||
const ranges = breakdown.ranges || [];
|
||||
const decoded = getParsedDecoded(pkt);
|
||||
const pathHops = getParsedPath(pkt);
|
||||
const decoded = getParsedDecoded(pkt) || {};
|
||||
const pathHops = getParsedPath(pkt) || [];
|
||||
|
||||
// Resolve sender GPS — from packet directly, or from known node in DB
|
||||
let senderLat = decoded.lat != null ? decoded.lat : (decoded.latitude || null);
|
||||
|
||||
@@ -4183,7 +4183,17 @@ console.log('\n=== app.js: routeTypeName/payloadTypeName edge cases ===');
|
||||
assertJsonEqual(getParsedPath(p), []);
|
||||
});
|
||||
|
||||
test('getParsedPath: cached null _parsedPath returns empty array (#538)', () => {
|
||||
const p = { path_json: '["a"]', _parsedPath: null };
|
||||
assertJsonEqual(getParsedPath(p), []);
|
||||
});
|
||||
|
||||
// --- getParsedDecoded ---
|
||||
test('getParsedDecoded: cached null _parsedDecoded returns empty object (#538)', () => {
|
||||
const p = { decoded_json: '{"x":1}', _parsedDecoded: null };
|
||||
assertJsonEqual(getParsedDecoded(p), {});
|
||||
});
|
||||
|
||||
test('getParsedDecoded: valid JSON object', () => {
|
||||
const p = { decoded_json: '{"type":"GRP_TXT","text":"hello"}' };
|
||||
const result = getParsedDecoded(p);
|
||||
|
||||
Reference in new issue
Block a user