Files
simtrace-analyser/frontend/sw.js
T
catarrh ac424e67e3 Files view: name the phonebook files from the card's EF_PBR (v2.7.7)
- EF_PBR (TS 31.102 §4.4.2.1) is the card's declaration of its phonebook:
  the constructed tags A8/A9/AA announce the type-1/2/3 groups and each nested
  primitive tag C0…CC names the file kind plus its FID — and, in a three-byte
  object, its SFI (length 2 = FID only).  pySim has no parser for it (its
  EF_PBR class still carries a "# TODO: a80ac0034f3a…" stub), so the decoder
  follows the spec: new simtrace_analyser/pbr.py
- the tracker decodes every EF_PBR record it observes (a READ RECORD's data
  or an UPDATE RECORD's body) and uses it for the DF it belongs to: the
  phonebook files get their symbolic names (4FA1 = EF_PBC, 4F3A = EF_ADN,
  4F01 = EF_IAP, 4F4A = EF_EXT1, 4F3D = EF_CCP1, 4F61 = EF_EMAIL, …), an
  earlier placeholder name is upgraded when the PBR arrives later, and the
  declared SFIs feed the DF's SFI→FID map (so SFI-addressed reads resolve
  without waiting for an FCP)
- verified on the live sessions 47/193:
  DF_TELECOM/DF_PHONEBOOK/EF_PBC (4FA1) and the SFI map
  {2→4F3A, 4→4FA1, 6→4F4A, 7→4F4F}
- also fixed: the "SFI = FID's five low bits" fallback (TS 102 221
  §11.1.1.4.8) no longer applies to a DF/ADF's FCP, which has no SFI
- tests: tests/test_pbr.py (the two real records, SFI-less objects, padding,
  truncation, merging, the shape check) and tracker cases (names, path,
  SFI map, the later-PBR upgrade); 537 Python + 76 Node tests
- README/README_RUS document the PBR naming; PWA_VERSION/pyproject/
  version.py 2.7.7, SW cache simtrace-analyser-v87
2026-10-18 01:18:26 +03:00

49 lines
1.4 KiB
JavaScript

const CACHE = 'simtrace-analyser-v87';
const PRECACHE = [
'index.html',
'manifest.json',
'icon-192.png',
'icon-512.png',
'favicon.png',
'sim-analyser.svg',
'sim-analyser-light.svg',
];
self.addEventListener('install', e => {
self.skipWaiting();
e.waitUntil(
caches.open(CACHE)
.then(cache => cache.addAll(PRECACHE))
.then(() => console.log('SW: precache done'))
.catch(err => console.error('SW: precache failed', err))
);
});
self.addEventListener('activate', e => {
e.waitUntil(
caches.keys()
.then(keys => Promise.all(
keys.filter(k => k !== CACHE).map(k => caches.delete(k))
))
.then(() => self.clients.claim())
.then(() => console.log('SW: activated, controlling clients'))
);
});
self.addEventListener('fetch', e => {
// Network-first: the local server is always up, so always serve fresh
// content and fall back to cache only when offline.
if (!e.request.url.startsWith('http')) return;
if (e.request.method !== 'GET') return;
e.respondWith(
fetch(e.request)
.then(r => {
const clone = r.clone();
caches.open(CACHE).then(c => c.put(e.request, clone)).catch(() => {});
return r;
})
.catch(() => caches.match(e.request))
);
});