Skip to content

Commit 721b730

Browse files
committed
retrospective
1 parent cd4c89f commit 721b730

File tree

76 files changed

+882
-619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+882
-619
lines changed

Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: clean install dev valid test prod
1+
.PHONY: clean install dev valid test prod serve_mirror
22
.DEFAULT_GOAL := dev
33
DENO_DEV = NODE_ENV=development deno run --watch
44
DENO_PROD = NODE_ENV=production deno run
@@ -30,5 +30,12 @@ test: valid
3030
prod: test
3131
rm -rf $(BUILD_DIR) $(CHROME_ZIP)
3232
$(DENO_PROD) $(DENO_OPTIONS) $(BUILD_SCRIPT)
33+
3334
zip -r $(CHROME_ZIP) $(OUTPUT_DIR) ./manifest.json > /dev/null
34-
tree -Dis $(BUILD_DIR) *.zip
35+
zip --delete $(CHROME_ZIP) "$(OUTPUT_DIR)mirror.html" "$(BUILD_DIR)mirror/*" > /dev/null
36+
37+
tree -Dis $(BUILD_DIR) *.zip | grep -E "api|zip"
38+
39+
serve_mirror:
40+
echo "http://localhost:5555/mirror.html 🎗 reminder to switch extension off"
41+
python3 -m http.server 5555 -d ./public/

build.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const buildOptions: BuildOptions = {
1717
'./src/api-monitor-cs-main.ts',
1818
'./src/api-monitor-cs-isolated.ts',
1919
'./src/api-monitor-devtools-panel.ts',
20+
'./src/mirror/mirror.ts',
2021
],
2122
outdir: './public/build/',
2223
define: {

manifest.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"version": "1.3.0",
3+
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxQCaHgX3DkPnGmHr+rhWyPvYemxMhBbvulmj4RvEpAnGVprdPCUiHSY0jOcDn3vnU6zm8mR1mT3sdlYoUGikBIT19/Jf1iGlc2dySt2bmDQXlTrqllT/XB8HW/wruFej9waMw9yqtW1wOJtElxWnT11pzXkKeflH1Sh+//Jnplr577vOmWh9TU8JLJHS9WklPHJyXCCMGrg/0Sxqte5qWryE2yIm9375KGkKN4ZKjSIxaCg0qodhf5Ug9s2QD7/s5xt548gbEUm9LqQHkNoIH3KXuYOnLksJFxi7FDwhg+oXalsONr5eEvPjkwxYpMKJXfRSg8sB8N6cXLUfgLAKUwIDAQAB",
34
"name": "API Monitor",
45
"manifest_version": 3,
56
"description": "Show active intervals, scheduled timeouts, animation frames, idle callbacks, eval invocations, media events and properties",

public/mirror.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
7+
<title>Mirror - Browser API Monitor</title>
8+
9+
<link rel="icon" type="image/png" href="./img/panel-icon28.png" />
10+
<link rel="stylesheet" href="./global.css" />
11+
<link rel="stylesheet" href="./build/mirror/mirror.css" />
12+
13+
<!-- <link href="devtools://theme/colors.css?sets=ui,chrome" rel="stylesheet" type="text/css" /> -->
14+
15+
<script async src="./build/api-monitor-cs-main.js"></script>
16+
<script async src="./build/mirror/mirror.js"></script>
17+
</head>
18+
19+
<body></body>
20+
</html>

src/api-monitor-cs-isolated.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ import {
55
windowListen,
66
windowPost,
77
} from './api/communication.ts';
8-
import { loadLocalStorage, onLocalStorageChange } from './api/storage.local.ts';
8+
import {
9+
loadLocalStorage,
10+
onLocalStorageChange,
11+
} from './api/storage/storage.local.ts';
912
import {
1013
loadSessionStorage,
1114
onSessionStorageChange,
12-
} from './api/storage.session.ts';
15+
} from './api/storage/storage.session.ts';
1316

1417
Promise.all([loadLocalStorage(), loadSessionStorage()]).then(
1518
([config, session]) => {
@@ -23,11 +26,11 @@ Promise.all([loadLocalStorage(), loadSessionStorage()]).then(
2326
portListen(windowPost);
2427
windowListen(runtimePost);
2528

26-
onLocalStorageChange((newValue) => {
27-
windowPost({ msg: EMsg.CONFIG, config: newValue });
29+
onLocalStorageChange((config) => {
30+
windowPost({ msg: EMsg.CONFIG, config });
2831
});
29-
onSessionStorageChange((newValue) => {
30-
windowPost({ msg: EMsg.SESSION, session: newValue });
32+
onSessionStorageChange((session) => {
33+
windowPost({ msg: EMsg.SESSION, session });
3134
});
3235

3336
runtimePost({ msg: EMsg.CONTENT_SCRIPT_LOADED });

src/api-monitor-cs-main.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,29 @@ const tick = new Timer(
4747
);
4848

4949
windowListen((o) => {
50-
if (o.msg === EMsg.TELEMETRY_ACKNOWLEDGED) {
50+
if (EMsg.TELEMETRY_ACKNOWLEDGED === o.msg) {
5151
tick.delay = adjustTelemetryDelay(o.timeOfCollection);
5252
originalMetrics = currentMetrics;
5353
eachSecond.isPending() && tick.start();
54-
} else if (
55-
o.msg === EMsg.CONFIG && o.config && typeof o.config === 'object'
56-
) {
54+
} else if (EMsg.CONFIG === o.msg) {
5755
applyConfig(o.config);
58-
} else if (o.msg === EMsg.START_OBSERVE) {
56+
} else if (EMsg.START_OBSERVE === o.msg) {
5957
originalMetrics = currentMetrics = null;
6058
tick.trigger();
6159
eachSecond.start();
62-
} else if (o.msg === EMsg.STOP_OBSERVE) {
60+
} else if (EMsg.STOP_OBSERVE === o.msg) {
6361
tick.stop();
6462
eachSecond.stop();
6563
originalMetrics = currentMetrics = null;
66-
} else if (o.msg === EMsg.RESET_WRAPPER_HISTORY) {
64+
} else if (EMsg.RESET_WRAPPER_HISTORY === o.msg) {
6765
originalMetrics = currentMetrics = null;
6866
cleanHistory();
6967
!tick.isPending() && tick.trigger();
70-
} else if (o.msg === EMsg.TIMER_COMMAND) {
68+
} else if (EMsg.TIMER_COMMAND === o.msg) {
7169
runTimerCommand(o.type, o.handler);
72-
} else if (o.msg === EMsg.MEDIA_COMMAND) {
70+
} else if (EMsg.MEDIA_COMMAND === o.msg) {
7371
runMediaCommand(o.mediaId, o.cmd, o.property);
74-
} else if (o.msg === EMsg.SESSION) {
72+
} else if (EMsg.SESSION === o.msg) {
7573
applySession(o.session);
7674
}
7775
});

src/api-monitor-devtools-panel.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { mount } from 'svelte';
22
import App from './view/App.svelte';
33
import { initConfigState } from './state/config.state.svelte.ts';
44
import { onHidePanel } from './devtoolsPanelUtil.ts';
5+
import { establishTelemetryReceiver } from './state/telemetry.state.svelte.ts';
56

67
initConfigState().then(() => {
78
mount(App, { target: document.body });
9+
establishTelemetryReceiver();
810
globalThis.addEventListener('beforeunload', onHidePanel);
911
});

src/api-monitor-devtools.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { EMsg, portPost } from './api/communication.ts';
2-
import { loadLocalStorage, saveLocalStorage } from './api/storage.local.ts';
3-
import { enableSessionInContentScript } from './api/storage.session.ts';
2+
import {
3+
loadLocalStorage,
4+
saveLocalStorage,
5+
} from './api/storage/storage.local.ts';
6+
import { enableSessionInContentScript } from './api/storage/storage.session.ts';
47
import { onHidePanel } from './devtoolsPanelUtil.ts';
58

69
// tabId may be null if user opened the devtools of the devtools

src/api/communication.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,26 @@ import { APPLICATION_NAME } from './env.ts';
1414
import { ERRORS_IGNORED } from './const.ts';
1515
import { ETimerType } from '../wrapper/TimerWrapper.ts';
1616
import type { TTelemetry } from '../wrapper/Wrapper.ts';
17-
import type { TConfig } from './storage.local.ts';
17+
import type { TConfig } from './storage/storage.local.ts';
1818
import type { TMediaCommand } from '../wrapper/MediaWrapper.ts';
1919
import type { Delta } from 'jsondiffpatch';
20-
import type { TSession } from './storage.session.ts';
20+
import type { TSession } from './storage/storage.session.ts';
2121

2222
let port: chrome.runtime.Port | null = null;
2323
export function portPost(payload: TMsgOptions) {
24+
if (!chrome.runtime) {
25+
windowPost(payload);
26+
return;
27+
}
28+
2429
if (!port) {
2530
port = chrome.tabs.connect(chrome.devtools.inspectedWindow.tabId, {
2631
name: APPLICATION_NAME,
2732
});
28-
port.onDisconnect.addListener(() => void (port = null));
33+
port?.onDisconnect.addListener(() => void (port = null));
2934
}
3035

31-
port.postMessage(payload);
36+
port?.postMessage(payload);
3237
}
3338

3439
export function portListen(callback: (payload: TMsgOptions) => void) {
@@ -67,16 +72,20 @@ export function runtimePost(payload: TMsgOptions) {
6772
}
6873

6974
export function runtimeListen(callback: (payload: TMsgOptions) => void) {
70-
chrome.runtime.onMessage.addListener(
71-
(payload, sender: chrome.runtime.MessageSender, sendResponse) => {
72-
if (
73-
sender.tab?.id === chrome.devtools.inspectedWindow.tabId
74-
) {
75-
callback(payload);
76-
sendResponse();
77-
}
78-
},
79-
);
75+
if (chrome?.runtime) {
76+
chrome.runtime.onMessage.addListener(
77+
(payload, sender: chrome.runtime.MessageSender, sendResponse) => {
78+
if (
79+
sender.tab?.id === chrome.devtools.inspectedWindow.tabId
80+
) {
81+
callback(payload);
82+
sendResponse();
83+
}
84+
},
85+
);
86+
} else {
87+
windowListen(callback);
88+
}
8089
}
8190

8291
function handleRuntimeMessageResponse(): void {

src/api/const.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export const ERRORS_IGNORED = [
66
];
77
export const TELEMETRY_FREQUENCY_30PS = 33.3333333333; // ms
88
export const TELEMETRY_FREQUENCY_1PS = 1000; // ms
9-
export const FRAME_1of60 = 0.0166666666667; // ms
9+
export const TIME_60FPS_SEC = 0.0166666666667; // s
10+
export const TIME_60FPS_MS = 16.666666666666668;
1011
export const VARIABLE_ANIMATION_THROTTLE = 3500; // eye blinking average frequency
1112
export const SELF_TIME_MAX_GOOD = 13.333333333333332; // ms
1213

src/api/storage.local.ts renamed to src/api/storage/storage.local.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import type {
22
TCancelIdleCallbackHistory,
33
TRequestIdleCallbackHistory,
4-
} from '../wrapper/IdleWrapper.ts';
4+
} from '../../wrapper/IdleWrapper.ts';
55
import type {
66
TCancelAnimationFrameHistory,
77
TRequestAnimationFrameHistory,
8-
} from '../wrapper/AnimationWrapper.ts';
8+
} from '../../wrapper/AnimationWrapper.ts';
99
import type {
1010
TClearTimerHistory,
1111
TSetTimerHistory,
12-
} from '../wrapper/TimerWrapper.ts';
12+
} from '../../wrapper/TimerWrapper.ts';
13+
import { CONFIG_VERSION, local } from './storage.ts';
1314

1415
type TPanelKey =
1516
| 'callsSummary'
@@ -24,19 +25,20 @@ type TPanelKey =
2425
| 'cancelAnimationFrame'
2526
| 'requestIdleCallback'
2627
| 'cancelIdleCallback';
27-
export type TPanelMap = {
28-
[K in TPanelKey]: TPanel;
29-
};
28+
3029
export type TPanel = {
3130
key: TPanelKey;
3231
label: string;
3332
visible: boolean;
3433
wrap: boolean | null;
3534
};
35+
export type TPanelMap = {
36+
[K in TPanelKey]: TPanel;
37+
};
38+
3639
export type TConfig = typeof DEFAULT_CONFIG;
3740
export type TConfigField = Partial<TConfig>;
3841

39-
const CONFIG_VERSION = '2025-04-25';
4042
export const DEFAULT_PANELS: TPanel[] = [
4143
{ key: 'callsSummary', label: 'Calls Summary', visible: false, wrap: null },
4244
{ key: 'media', label: 'Media', visible: true, wrap: null },
@@ -143,32 +145,36 @@ export function panelsArray2Map(panels: TPanel[]) {
143145
}
144146

145147
export async function loadLocalStorage(): Promise<TConfig> {
146-
let store = await chrome.storage.local.get([CONFIG_VERSION]);
148+
let store = await local.get([CONFIG_VERSION]);
147149
const isEmpty = !Object.keys(store).length;
148150

149151
if (isEmpty) {
150-
await chrome.storage.local.clear(); // reset previous version
151-
await chrome.storage.local.set({ [CONFIG_VERSION]: DEFAULT_CONFIG });
152-
store = await chrome.storage.local.get([CONFIG_VERSION]);
152+
await local.clear(); // reset previous version
153+
await local.set({ [CONFIG_VERSION]: DEFAULT_CONFIG });
154+
store = await local.get([CONFIG_VERSION]);
153155
}
154156

155157
return store[CONFIG_VERSION];
156158
}
157159

158160
export async function saveLocalStorage(value: TConfigField) {
159-
const store = await chrome.storage.local.get([CONFIG_VERSION]);
161+
const store = await local.get([CONFIG_VERSION]);
160162

161163
Object.assign(store[CONFIG_VERSION], value);
162164

163-
return await chrome.storage.local.set(store);
165+
return await local.set(store);
164166
}
165167

166168
export function onLocalStorageChange(
167169
callback: (newValue: TConfig, oldValue: TConfig) => void,
168170
) {
169-
chrome.storage.local.onChanged.addListener((change) => {
171+
local.onChanged.addListener((change: {
172+
[key: string]: chrome.storage.StorageChange;
173+
}) => {
170174
if (
171-
change && change[CONFIG_VERSION] && change[CONFIG_VERSION].newValue
175+
change &&
176+
change[CONFIG_VERSION] &&
177+
change[CONFIG_VERSION].newValue
172178
) {
173179
callback(
174180
change[CONFIG_VERSION].newValue,

src/api/storage.session.ts renamed to src/api/storage/storage.session.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const SESSION_VERSION = '2025-04-25';
1+
import { session, SESSION_VERSION } from './storage.ts';
22

33
export type TSession = typeof DEFAULT_SESSION;
44
type TSessionProperty = Partial<TSession>;
@@ -8,36 +8,36 @@ const DEFAULT_SESSION = {
88
};
99

1010
export function enableSessionInContentScript() {
11-
return chrome.storage.session.setAccessLevel({
11+
return session.setAccessLevel({
1212
accessLevel: 'TRUSTED_AND_UNTRUSTED_CONTEXTS',
1313
});
1414
}
1515

1616
export async function loadSessionStorage(): Promise<TSession> {
17-
let store = await chrome.storage.session.get([SESSION_VERSION]);
17+
let store = await session.get([SESSION_VERSION]);
1818
const isEmpty = !Object.keys(store).length;
1919

2020
if (isEmpty) {
21-
await chrome.storage.session.clear(); // reset previous version
22-
await chrome.storage.session.set({ [SESSION_VERSION]: DEFAULT_SESSION });
23-
store = await chrome.storage.session.get([SESSION_VERSION]);
21+
await session.clear(); // reset previous version
22+
await session.set({ [SESSION_VERSION]: DEFAULT_SESSION });
23+
store = await session.get([SESSION_VERSION]);
2424
}
2525

2626
return store[SESSION_VERSION];
2727
}
2828

2929
export async function saveSessionStorage(value: TSessionProperty) {
30-
const store = await chrome.storage.session.get([SESSION_VERSION]);
30+
const store = await session.get([SESSION_VERSION]);
3131

3232
Object.assign(store[SESSION_VERSION], value);
3333

34-
return await chrome.storage.session.set(store);
34+
return await session.set(store);
3535
}
3636

3737
export function onSessionStorageChange(
3838
callback: (newValue: TSession, oldValue: TSession) => void,
3939
) {
40-
chrome.storage.session.onChanged.addListener((change) => {
40+
session.onChanged.addListener((change) => {
4141
if (
4242
change && change[SESSION_VERSION] && change[SESSION_VERSION].newValue
4343
) {

0 commit comments

Comments
 (0)