Skip to content

Commit bcffd25

Browse files
committed
Error logging
1 parent 29e668e commit bcffd25

File tree

14 files changed

+1101
-186
lines changed

14 files changed

+1101
-186
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,14 @@ node build.js
5151

5252
* [ ] `GM_download`
5353
* [ ] `GM_confirm`
54+
* [ ] `GM_unregisterMenuCommand`
5455
* [ ] Additional APIs as needed
5556

5657
### Security & Permissions
5758

5859
* [ ] Add new security settings
5960
* [ ] Allow scripts to load external resources
60-
* [ ] Enable loading of third-party libraries and external scripts
6161
* [ ] Ask for confirmation when a script runs on a website for the first time
62-
* [ ] Centralize script access permission checks
6362
* [ ] Add better trusted type managment
6463

6564
### Core Improvements
@@ -71,6 +70,7 @@ node build.js
7170
* [ ] Refine `getScriptDescription` function
7271
* [ ] Deduplicate logic between `background.js`, `inject.js`, and `GM_core.js`
7372
* [ ] Unify or reuse declarations between `GM_core` and `inject`
73+
* [ ] Make menu commands reactive
7474

7575
### Editor
7676

@@ -86,7 +86,6 @@ node build.js
8686
* [ ] Add a cap to how long text can be in the editor
8787

8888
### UI
89-
* [ ] Refine CSS for menu commands
9089
* [ ] Add iframe preview with live refresh
9190
* [ ] Fix editor optimizations
9291
* [ ] Add a cap to how long text can be in the dashboard

src/GM/gmApiDefinitions.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ export const GM_API_DEFINITIONS = {
9494
category: GM_API_CATEGORIES.BROWSER_UI,
9595
description: "Adds a custom command to the userscript menu"
9696
},
97+
GM_unregisterMenuCommand: {
98+
signature: "declare function GM_unregisterMenuCommand(commandId: string): void;",
99+
name: "GM_unregisterMenuCommand",
100+
el: "gmUnregisterMenuCommand",
101+
tmName: "GM_unregisterMenuCommand",
102+
category: GM_API_CATEGORIES.BROWSER_UI,
103+
description: "Removes a previously registered menu command"
104+
},
97105

98106
// Resources & Network APIs
99107
GM_getResourceText: {

src/GM/gm_core.js

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,26 @@
242242
};
243243
window.GM_registerMenuCommand = window.GM.registerMenuCommand = fn;
244244
}
245+
246+
if (e.gmUnregisterMenuCommand) {
247+
const fn = (commandId) => {
248+
if (typeof commandId !== "string") {
249+
console.warn(
250+
"GM_unregisterMenuCommand: Expected string commandId"
251+
);
252+
return;
253+
}
254+
if (window.__gmMenuCommands) {
255+
const index = window.__gmMenuCommands.findIndex(
256+
(cmd) => cmd.commandId === commandId
257+
);
258+
if (index !== -1) {
259+
window.__gmMenuCommands.splice(index, 1);
260+
}
261+
}
262+
};
263+
window.GM_unregisterMenuCommand = window.GM.unregisterMenuCommand = fn;
264+
}
245265
}
246266

247267
// ---- RESOURCES ----
@@ -391,8 +411,61 @@
391411

392412
// Helper to execute user code after ensuring @require dependencies are loaded.
393413
async function executeUserScriptWithDependencies(userCode, scriptId, requireUrls, loader) {
414+
// Setup error capturing for this script
415+
const errorHandler = (event) => {
416+
// Check if error is from our script by checking the error stack
417+
const stack = event.error?.stack || event.reason?.stack || '';
418+
const message = event.error?.message || event.reason?.message || event.message || 'Unknown error';
419+
420+
// Report error to editor
421+
try {
422+
const errorData = {
423+
type: 'SCRIPT_ERROR',
424+
scriptId: scriptId,
425+
error: {
426+
message: message,
427+
stack: stack,
428+
timestamp: new Date().toISOString(),
429+
type: 'error'
430+
}
431+
};
432+
window.postMessage(errorData, '*');
433+
} catch (e) {
434+
console.error('[CodeTweak Error Capture] Failed to report script error:', e);
435+
}
436+
};
437+
438+
const rejectionHandler = (event) => {
439+
const message = event.reason?.message || String(event.reason) || 'Unhandled promise rejection';
440+
const stack = event.reason?.stack || '';
441+
442+
// Report error to editor
443+
try {
444+
const errorData = {
445+
type: 'SCRIPT_ERROR',
446+
scriptId: scriptId,
447+
error: {
448+
message: message,
449+
stack: stack,
450+
timestamp: new Date().toISOString(),
451+
type: 'error'
452+
}
453+
};
454+
window.postMessage(errorData, '*');
455+
} catch (e) {
456+
console.error('[CodeTweak Error Capture] Failed to report script error:', e);
457+
}
458+
};
459+
460+
// Add error listeners
461+
window.addEventListener('error', errorHandler);
462+
window.addEventListener('unhandledrejection', rejectionHandler);
463+
394464
try {
395465
await loader.loadScripts(requireUrls);
466+
467+
// Don't wrap user code in try-catch - let errors bubble to global handlers
468+
// This ensures we catch ALL errors, including those in user's try-catch blocks
396469
const blob = new Blob([userCode], { type: "text/javascript" });
397470
const blobUrl = URL.createObjectURL(blob);
398471

@@ -422,24 +495,57 @@
422495

423496
scriptEl.src = trustedSrc;
424497
scriptEl.async = false; // maintain order
498+
scriptEl.setAttribute('data-script-id', scriptId);
425499
scriptEl.onload = () => {
426500
URL.revokeObjectURL(blobUrl);
427501
resolve();
428502
};
429503
scriptEl.onerror = (event) => {
430504
URL.revokeObjectURL(blobUrl);
431-
reject(
432-
new Error(
433-
`Failed to execute user script ${scriptId}: ${event?.message || "unknown error"}`
434-
)
505+
const error = new Error(
506+
`Failed to execute user script ${scriptId}: ${event?.message || "unknown error"}`
435507
);
508+
509+
// Report load error
510+
try {
511+
window.postMessage({
512+
type: 'SCRIPT_ERROR',
513+
scriptId: scriptId,
514+
error: {
515+
message: error.message,
516+
stack: error.stack || '',
517+
timestamp: new Date().toISOString(),
518+
type: 'error'
519+
}
520+
}, '*');
521+
} catch (e) {
522+
console.error('Failed to report script load error:', e);
523+
}
524+
525+
reject(error);
436526
};
437527
(document.head || document.documentElement || document.body).appendChild(
438528
scriptEl
439529
);
440530
});
441531
} catch (err) {
442532
console.error(`CodeTweak: Error executing user script ${scriptId}:`, err);
533+
534+
// Report execution error
535+
try {
536+
window.postMessage({
537+
type: 'SCRIPT_ERROR',
538+
scriptId: scriptId,
539+
error: {
540+
message: err.message || 'Script execution failed',
541+
stack: err.stack || '',
542+
timestamp: new Date().toISOString(),
543+
type: 'error'
544+
}
545+
}, '*');
546+
} catch (e) {
547+
console.error('Failed to report script execution error:', e);
548+
}
443549
}
444550
}
445551

src/assets/styles/d_script_list.css

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
/* Scripts Table Header */
2+
.scripts-table-header {
3+
display: grid;
4+
grid-template-columns: 48px minmax(250px, 2fr) 100px minmax(150px, 1.5fr) minmax(150px, 1.5fr) 120px 100px;
5+
gap: var(--space-md);
6+
padding: var(--space-sm) var(--space-md);
7+
background: var(--bg-tertiary);
8+
border-bottom: 2px solid var(--border-primary);
9+
font-size: var(--font-sm);
10+
font-weight: 600;
11+
color: var(--text-secondary);
12+
text-transform: uppercase;
13+
letter-spacing: 0.5px;
14+
position: sticky;
15+
top: 0;
16+
z-index: 10;
17+
}
18+
19+
.scripts-table-header > div {
20+
display: flex;
21+
align-items: center;
22+
gap: 4px;
23+
}
24+
25+
126
/* Scripts List */
227
.scripts-list {
328
flex: 1;
@@ -14,34 +39,83 @@
1439
border-radius: var(--radius-md);
1540
padding: var(--space-md);
1641
display: grid;
17-
grid-template-columns: auto 1fr auto auto;
42+
grid-template-columns: 48px minmax(250px, 2fr) 100px minmax(150px, 1.5fr) minmax(150px, 1.5fr) 120px 100px;
1843
gap: var(--space-md);
1944
align-items: center;
2045
transition: var(--transition-all);
46+
overflow: hidden;
47+
}
48+
49+
.script-list-item:hover {
50+
border-color: var(--primary);
51+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
2152
}
2253

23-
.script-list-item .script-name {
54+
/* Name Column */
55+
.script-name-col {
56+
min-width: 0;
57+
overflow: hidden;
58+
}
59+
60+
.script-name {
2461
font-weight: 500;
62+
font-size: var(--font-md);
2563
color: var(--text-primary);
64+
white-space: nowrap;
65+
overflow: hidden;
66+
text-overflow: ellipsis;
67+
margin: 0 0 4px 0;
2668
}
2769

28-
.script-list-item .script-version {
70+
.script-description {
71+
font-size: var(--font-sm);
72+
color: var(--text-secondary);
73+
white-space: nowrap;
74+
overflow: hidden;
75+
text-overflow: ellipsis;
76+
margin: 0;
77+
}
78+
79+
/* Version Column */
80+
.script-version-col {
2981
font-size: var(--font-sm);
3082
color: var(--text-muted);
83+
font-family: 'Courier New', monospace;
3184
}
3285

33-
.script-list-item .script-description {
86+
/* Sites Column */
87+
.script-sites-col {
3488
font-size: var(--font-sm);
3589
color: var(--text-secondary);
3690
white-space: nowrap;
3791
overflow: hidden;
3892
text-overflow: ellipsis;
3993
}
4094

41-
.script-urls {
95+
.site-count {
96+
display: inline-block;
97+
padding: 2px 6px;
98+
background: var(--bg-tertiary);
99+
border-radius: var(--radius-sm);
42100
font-size: var(--font-xs);
43101
color: var(--text-muted);
44-
margin-top: 4px;
102+
margin-left: 4px;
103+
}
104+
105+
/* Features Column */
106+
.script-features-col {
107+
font-size: var(--font-sm);
108+
color: var(--text-secondary);
109+
white-space: nowrap;
110+
overflow: hidden;
111+
text-overflow: ellipsis;
112+
}
113+
114+
/* Run At Column */
115+
.script-runat-col {
116+
font-size: var(--font-sm);
117+
color: var(--text-muted);
118+
white-space: nowrap;
45119
}
46120

47121
.script-actions {

0 commit comments

Comments
 (0)