Skip to content

Commit cc54e34

Browse files
committed
ScriptVault v1.7.6: null safety across all UI pages
Prevent TypeError crashes from null DOM elements: - sidepanel.js: $ helper returns dummy div instead of null - devtools-panel.js: same null-safe $ helper - install.js: optional chaining on btn-cancel/btn-install/toggle-code listeners - popup.js: null check on blacklist .menu-item-text querySelector - dashboard.js: null check on command palette input, optional chaining on storage editor button listeners (save/rename/delete/keySpan)
1 parent 0015843 commit cc54e34

File tree

13 files changed

+32
-32
lines changed

13 files changed

+32
-32
lines changed

CLAUDE.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Modern userscript manager built with Chrome Manifest V3. Tampermonkey-inspired functionality with cloud sync, auto-updates, a full dashboard, Monaco editor, DevTools panel, and a persistent side panel.
55

66
## Version
7-
v1.7.5
7+
v1.7.6
88

99
## Tech Stack
1010
- Chrome MV3 extension (JavaScript)
@@ -88,8 +88,8 @@ v1.7.5
8888
- `cleanupStaleCaches()` runs on init to prune expired `require_cache_*`, `res_cache_*`, trash entries, and tombstones >30 days
8989
- Lint: `@grant none` + GM API usage shows `warning` severity (upgraded from `info` in v1.7.2). Unknown `@grant` values and invalid `@sandbox` values are `error` severity.
9090
- **Side panel / DevTools must use `action:` key** (not `type:`) for background messages. Background returns `{ scripts: [...] }` — callers need `res?.scripts`. `setScriptSettings` expects `scriptId` not `id`.
91-
- **GM_cookie_set/GM_cookie_delete** require `url` and `name` parameters (validated in v1.7.5)
92-
- **GM_unregisterMenuCommand** handler added in v1.7.5 — previously calls were silently dropped
91+
- **GM_cookie_set/GM_cookie_delete** require `url` and `name` parameters (validated in v1.7.6)
92+
- **GM_unregisterMenuCommand** handler added in v1.7.6 — previously calls were silently dropped
9393
- **XHR local request IDs** use sequential counter `_xhrSeqId++` (not `Math.random`) to prevent collision
9494
- **Notification callbacks** cleaned up on auto-timeout (not all platforms fire `onClosed`)
9595
- **Menu commands** cleaned from session storage when a script is deleted
@@ -163,7 +163,7 @@ v1.7.5
163163
- **Side panel**: responds to `chrome.tabs.onActivated` and `chrome.tabs.onUpdated` to refresh script list on navigation. Uses same `sendToBackground` pattern as popup.
164164
- **DevTools panel**: auto-refreshes every 3s. `getNetworkLog` returns flat array; `getNetworkLogStats` for totals. HAR export uses `URL.createObjectURL` + programmatic `<a>` click.
165165

166-
## v1.7.0 → v1.7.5 Audit (2026-03-24, 4 rounds)
166+
## v1.7.0 → v1.7.6 Audit (2026-03-24, 4 rounds)
167167

168168
### v1.7.0 — Major Feature Release
169169
- DevTools panel, Side panel, Script signing (Ed25519), Monaco editor adapter, Offscreen document
@@ -185,7 +185,7 @@ v1.7.5
185185
- GM_webRequest added to hints + grant values, duplicate hint directives removed
186186
- Dashboard: updated column defaults to desc sort, network log cap 500 -> 2000
187187

188-
### v1.7.5 — Memory Leaks & Validation
188+
### v1.7.6 — Memory Leaks & Validation
189189
- Added missing GM_unregisterMenuCommand handler (calls were silently dropped)
190190
- Menu commands cleaned from session storage on script delete
191191
- Notification callback cleanup on auto-timeout
@@ -232,7 +232,7 @@ v1.7.5
232232
- Fixed: NetworkLog duration calculation used `_netLogEntry.timestamp` which was undefined; replaced with dedicated `_netLogStartTime` variable
233233
- Fixed: `state.folders`, `state._collapsedFolders`, `state._lastCheckedId`, `state._quotaWarned` not initialized in dashboard state object
234234
- Fixed: `switchTab('help')` in command palette failed because help tab is a header icon, not a `.tm-tab`; added special case handling
235-
- Verified: All version strings match (v1.7.5 across manifest, manifest-firefox, content.js, popup.js, dashboard.js)
235+
- Verified: All version strings match (v1.7.6 across manifest, manifest-firefox, content.js, popup.js, dashboard.js)
236236
- Verified: All bg/ modules load before background.core.js in build output
237237
- Verified: `escapeHtml` available in popup.js (shared/utils.js loaded first)
238238
- Verified: Column index mapping still correct after pin button addition (pin is inside actions TD, not a new column)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</p>
1010

1111
<p align="center">
12-
<img src="https://img.shields.io/badge/version-1.7.5-22c55e?style=flat-square" alt="Version">
12+
<img src="https://img.shields.io/badge/version-1.7.6-22c55e?style=flat-square" alt="Version">
1313
<img src="https://img.shields.io/badge/manifest-v3-60a5fa?style=flat-square" alt="Manifest V3">
1414
<img src="https://img.shields.io/badge/license-MIT-orange?style=flat-square" alt="License">
1515
<img src="https://img.shields.io/badge/chrome-120%2B-blue?style=flat-square" alt="Chrome 120+">
@@ -325,6 +325,6 @@ MIT License &mdash; see [LICENSE](LICENSE) for details.
325325
---
326326

327327
<p align="center">
328-
<strong>ScriptVault v1.7.5</strong><br>
328+
<strong>ScriptVault v1.7.6</strong><br>
329329
<em>Your scripts, your rules &mdash; locked down and loaded</em>
330330
</p>

background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ScriptVault v1.7.5 - Background Service Worker
1+
// ScriptVault v1.7.6 - Background Service Worker
22
// Comprehensive userscript manager with cloud sync and auto-updates
33
// NOTE: This file is built from source modules. Edit the individual files in
44
// shared/, modules/, and lib/, then run build-background.sh to regenerate.

content.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ScriptVault v1.7.5 - Content Script Bridge
1+
// ScriptVault v1.7.6 - Content Script Bridge
22
// Bridges messages between userscripts (USER_SCRIPT world) and background service worker
33

44
(function() {

manifest-firefox.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "__MSG_extName__",
4-
"version": "1.7.5",
4+
"version": "1.7.6",
55
"description": "__MSG_extDescription__",
66
"default_locale": "en",
77
"homepage_url": "https://github.com/SysAdminDoc/ScriptVault",

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "__MSG_extName__",
4-
"version": "1.7.5",
4+
"version": "1.7.6",
55
"description": "__MSG_extDescription__",
66
"default_locale": "en",
77
"minimum_chrome_version": "120",

offscreen.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ScriptVault Offscreen Document v1.7.5
1+
// ScriptVault Offscreen Document v1.7.6
22
// Handles CPU-intensive tasks off the service worker:
33
// - AST-based script analysis (via Acorn)
44
// - 3-way text merge for sync conflict resolution

pages/dashboard.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ScriptVault Dashboard v1.7.5 - Full-Featured Controller
1+
// ScriptVault Dashboard v1.7.6 - Full-Featured Controller
22
(function() {
33
'use strict';
44

@@ -2422,15 +2422,15 @@
24222422

24232423
const keySpan = item.querySelector('.storage-key');
24242424

2425-
item.querySelector('.btn:first-of-type').addEventListener('click', async () => {
2425+
item.querySelector('.btn:first-of-type')?.addEventListener('click', async () => {
24262426
let newVal = item.querySelector('.input-field').value;
24272427
try { newVal = JSON.parse(newVal); } catch (e) {}
24282428
await chrome.runtime.sendMessage({ action: 'setScriptValue', scriptId, key: currentKey, value: newVal });
24292429
showToast('Saved', 'success');
24302430
});
24312431

24322432
// Rename button
2433-
item.querySelectorAll('.btn')[1].addEventListener('click', async () => {
2433+
item.querySelectorAll('.btn')[1]?.addEventListener('click', async () => {
24342434
const newKey = prompt('Rename key:', currentKey);
24352435
if (!newKey || newKey === currentKey) return;
24362436
const res = await chrome.runtime.sendMessage({ action: 'renameScriptValue', scriptId, oldKey: currentKey, newKey });
@@ -2444,9 +2444,9 @@
24442444
});
24452445

24462446
// Rename on key span click too
2447-
keySpan.addEventListener('click', () => item.querySelectorAll('.btn')[1].click());
2447+
keySpan?.addEventListener('click', () => item.querySelectorAll('.btn')[1]?.click());
24482448

2449-
item.querySelector('.btn-danger').addEventListener('click', async () => {
2449+
item.querySelector('.btn-danger')?.addEventListener('click', async () => {
24502450
if (await showConfirmModal('Delete', `Delete "${currentKey}"?`)) {
24512451
await chrome.runtime.sendMessage({ action: 'deleteScriptValue', scriptId, key: currentKey });
24522452
item.remove();
@@ -4859,8 +4859,7 @@
48594859

48604860
overlay.classList.add('open');
48614861
const input = overlay.querySelector('.cmd-input');
4862-
input.value = '';
4863-
input.focus();
4862+
if (input) { input.value = ''; input.focus(); }
48644863
renderCommandResults('');
48654864
}
48664865

pages/devtools-panel.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// ScriptVault DevTools Panel v1.7.5
1+
// ScriptVault DevTools Panel v1.7.6
22
// Network inspection, execution profiling, and console capture
33

44
(function () {
55
'use strict';
66

7-
const $ = id => document.getElementById(id);
7+
const $ = id => document.getElementById(id) || document.createElement('div'); // null-safe
88

99
let netLog = [];
1010
let scripts = [];
@@ -232,7 +232,7 @@
232232
comment: e.scriptName || ''
233233
}));
234234

235-
const har = { log: { version: '1.2', creator: { name: 'ScriptVault', version: '1.7.5' }, entries } };
235+
const har = { log: { version: '1.2', creator: { name: 'ScriptVault', version: '1.7.6' }, entries } };
236236
const blob = new Blob([JSON.stringify(har, null, 2)], { type: 'application/json' });
237237
const url = URL.createObjectURL(blob);
238238
const a = document.createElement('a');

pages/install.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ScriptVault Install Page v1.7.5
1+
// ScriptVault Install Page v1.7.6
22

33
// Dangerous permissions that warrant security warnings
44
const DANGEROUS_PERMISSIONS = [
@@ -526,9 +526,9 @@ function renderInstallUI(sourceUrl) {
526526
setupCodePreview();
527527

528528
// Setup event listeners
529-
document.getElementById('btn-cancel').addEventListener('click', handleCancel);
530-
document.getElementById('btn-install').addEventListener('click', handleInstall);
531-
document.getElementById('toggle-code').addEventListener('click', toggleCodePreview);
529+
document.getElementById('btn-cancel')?.addEventListener('click', handleCancel);
530+
document.getElementById('btn-install')?.addEventListener('click', handleInstall);
531+
document.getElementById('toggle-code')?.addEventListener('click', toggleCodePreview);
532532

533533
document.getElementById('enable-install')?.addEventListener('change', (e) => {
534534
enableOnInstall = e.target.checked;

0 commit comments

Comments
 (0)