diff --git a/packages/process-explorer-worker/src/parts/GetAttributionName/GetAttributionName.ts b/packages/process-explorer-worker/src/parts/GetAttributionName/GetAttributionName.ts new file mode 100644 index 0000000..2a19178 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/GetAttributionName/GetAttributionName.ts @@ -0,0 +1,11 @@ +import type { MemoryAttribution } from '../MemoryAttribution/MemoryAttribution.ts' +import * as GetUrlName from '../GetUrlName/GetUrlName.ts' + +export const getAttributionName = (attribution: MemoryAttribution): string => { + const scope = attribution.scope || 'memory' + const url = attribution.url ? GetUrlName.getUrlName(attribution.url) : '' + if (url) { + return `${scope}: ${url}` + } + return scope +} diff --git a/packages/process-explorer-worker/src/parts/GetBreakdownName/GetBreakdownName.ts b/packages/process-explorer-worker/src/parts/GetBreakdownName/GetBreakdownName.ts new file mode 100644 index 0000000..a831f5d --- /dev/null +++ b/packages/process-explorer-worker/src/parts/GetBreakdownName/GetBreakdownName.ts @@ -0,0 +1,17 @@ +import type { MemoryBreakdownEntry } from '../MemoryBreakdownEntry/MemoryBreakdownEntry.ts' +import * as GetAttributionName from '../GetAttributionName/GetAttributionName.ts' + +export const getBreakdownName = ( + entry: MemoryBreakdownEntry, + index: number, +): string => { + if (entry.attribution && entry.attribution.length > 0) { + return entry.attribution + .map(GetAttributionName.getAttributionName) + .join(', ') + } + if (entry.types && entry.types.length > 0) { + return entry.types.join(', ') + } + return `breakdown ${index + 1}` +} diff --git a/packages/process-explorer-worker/src/parts/GetFrontendMemoryUsage/GetFrontendMemoryUsage.ts b/packages/process-explorer-worker/src/parts/GetFrontendMemoryUsage/GetFrontendMemoryUsage.ts index 8bbabef..08456d0 100644 --- a/packages/process-explorer-worker/src/parts/GetFrontendMemoryUsage/GetFrontendMemoryUsage.ts +++ b/packages/process-explorer-worker/src/parts/GetFrontendMemoryUsage/GetFrontendMemoryUsage.ts @@ -1,116 +1,34 @@ import type { ProcessInfo } from '../ProcessInfo/ProcessInfo.ts' - -interface MemoryAttribution { - readonly scope?: string - readonly url?: string -} - -interface MemoryBreakdownEntry { - readonly attribution?: readonly MemoryAttribution[] - readonly bytes: number - readonly types?: readonly string[] -} - -interface MemoryMeasurement { - readonly breakdown?: readonly MemoryBreakdownEntry[] - readonly bytes: number -} - -interface PerformanceWithMemory extends Performance { - readonly measureUserAgentSpecificMemory?: () => Promise -} - -const WindowPid = -1 - -const QueryOrHashRegex = /[?#]/ - -const isValidMemoryValue = (value: unknown): value is number => { - return typeof value === 'number' && Number.isFinite(value) && value >= 0 -} - -const getMeasureMemory = (): (() => Promise) | undefined => { - const { measureUserAgentSpecificMemory } = - performance as PerformanceWithMemory - if (typeof measureUserAgentSpecificMemory !== 'function') { - return undefined - } - return measureUserAgentSpecificMemory.bind(performance) -} - -const getUrlName = (url: string): string => { - if (!url || url === 'cross-origin-url') { - return url - } - try { - const parsed = new URL(url) - const parts = parsed.pathname.split('/').filter(Boolean) - return parts.at(-1) || parsed.hostname || url - } catch { - const withoutQuery = url.split(QueryOrHashRegex, 1)[0] - const parts = withoutQuery.split('/').filter(Boolean) - return parts.at(-1) || url - } -} - -const getAttributionName = (attribution: MemoryAttribution): string => { - const scope = attribution.scope || 'memory' - const url = attribution.url ? getUrlName(attribution.url) : '' - if (url) { - return `${scope}: ${url}` - } - return scope -} - -const getBreakdownName = ( - entry: MemoryBreakdownEntry, - index: number, -): string => { - if (entry.attribution && entry.attribution.length > 0) { - return entry.attribution.map(getAttributionName).join(', ') - } - if (entry.types && entry.types.length > 0) { - return entry.types.join(', ') - } - return `breakdown ${index + 1}` -} - -const toBreakdownProcess = ( - entry: MemoryBreakdownEntry, - index: number, -): ProcessInfo => { - const name = getBreakdownName(entry, index) - return { - cmd: name, - memory: entry.bytes, - name, - pid: -2 - index, - ppid: WindowPid, - synthetic: true, - } -} +import * as GetMeasureMemory from '../GetMeasureMemory/GetMeasureMemory.ts' +import * as IsValidMemoryValue from '../IsValidMemoryValue/IsValidMemoryValue.ts' +import * as ToBreakdownProcess from '../ToBreakdownProcess/ToBreakdownProcess.ts' +import * as WindowPid from '../WindowPid/WindowPid.ts' export const getFrontendMemoryUsage = async ( rootPid: number, ): Promise => { - const measureMemory = getMeasureMemory() + const measureMemory = GetMeasureMemory.getMeasureMemory() if (!measureMemory) { return [] } try { const measurement = await measureMemory() - if (!isValidMemoryValue(measurement.bytes)) { + if (!IsValidMemoryValue.isValidMemoryValue(measurement.bytes)) { return [] } const breakdown = measurement.breakdown || [] const breakdownProcesses = breakdown - .filter((entry) => isValidMemoryValue(entry.bytes) && entry.bytes > 0) - .map(toBreakdownProcess) + .filter( + (entry) => + IsValidMemoryValue.isValidMemoryValue(entry.bytes) && entry.bytes > 0, + ) + .map(ToBreakdownProcess.toBreakdownProcess) return [ { cmd: 'window', memory: measurement.bytes, name: 'window', - pid: WindowPid, + pid: WindowPid.WindowPid, ppid: rootPid, synthetic: true, }, diff --git a/packages/process-explorer-worker/src/parts/GetMeasureMemory/GetMeasureMemory.ts b/packages/process-explorer-worker/src/parts/GetMeasureMemory/GetMeasureMemory.ts new file mode 100644 index 0000000..a7433e7 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/GetMeasureMemory/GetMeasureMemory.ts @@ -0,0 +1,12 @@ +import type { MemoryMeasurement } from '../MemoryMeasurement/MemoryMeasurement.ts' +import type { PerformanceWithMemory } from '../PerformanceWithMemory/PerformanceWithMemory.ts' + +export const getMeasureMemory = (): + (() => Promise) | undefined => { + const { measureUserAgentSpecificMemory } = + performance as PerformanceWithMemory + if (typeof measureUserAgentSpecificMemory !== 'function') { + return undefined + } + return measureUserAgentSpecificMemory.bind(performance) +} diff --git a/packages/process-explorer-worker/src/parts/GetUrlName/GetUrlName.ts b/packages/process-explorer-worker/src/parts/GetUrlName/GetUrlName.ts new file mode 100644 index 0000000..8cef045 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/GetUrlName/GetUrlName.ts @@ -0,0 +1,16 @@ +const QueryOrHashRegex = /[?#]/ + +export const getUrlName = (url: string): string => { + if (!url || url === 'cross-origin-url') { + return url + } + try { + const parsed = new URL(url) + const parts = parsed.pathname.split('/').filter(Boolean) + return parts.at(-1) || parsed.hostname || url + } catch { + const withoutQuery = url.split(QueryOrHashRegex, 1)[0] + const parts = withoutQuery.split('/').filter(Boolean) + return parts.at(-1) || url + } +} diff --git a/packages/process-explorer-worker/src/parts/IsValidMemoryValue/IsValidMemoryValue.ts b/packages/process-explorer-worker/src/parts/IsValidMemoryValue/IsValidMemoryValue.ts new file mode 100644 index 0000000..16948b9 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/IsValidMemoryValue/IsValidMemoryValue.ts @@ -0,0 +1,3 @@ +export const isValidMemoryValue = (value: unknown): value is number => { + return typeof value === 'number' && Number.isFinite(value) && value >= 0 +} diff --git a/packages/process-explorer-worker/src/parts/MemoryAttribution/MemoryAttribution.ts b/packages/process-explorer-worker/src/parts/MemoryAttribution/MemoryAttribution.ts new file mode 100644 index 0000000..286303b --- /dev/null +++ b/packages/process-explorer-worker/src/parts/MemoryAttribution/MemoryAttribution.ts @@ -0,0 +1,4 @@ +export interface MemoryAttribution { + readonly scope?: string + readonly url?: string +} diff --git a/packages/process-explorer-worker/src/parts/MemoryBreakdownEntry/MemoryBreakdownEntry.ts b/packages/process-explorer-worker/src/parts/MemoryBreakdownEntry/MemoryBreakdownEntry.ts new file mode 100644 index 0000000..acd7fb1 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/MemoryBreakdownEntry/MemoryBreakdownEntry.ts @@ -0,0 +1,7 @@ +import type { MemoryAttribution } from '../MemoryAttribution/MemoryAttribution.ts' + +export interface MemoryBreakdownEntry { + readonly attribution?: readonly MemoryAttribution[] + readonly bytes: number + readonly types?: readonly string[] +} diff --git a/packages/process-explorer-worker/src/parts/MemoryMeasurement/MemoryMeasurement.ts b/packages/process-explorer-worker/src/parts/MemoryMeasurement/MemoryMeasurement.ts new file mode 100644 index 0000000..eda1877 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/MemoryMeasurement/MemoryMeasurement.ts @@ -0,0 +1,6 @@ +import type { MemoryBreakdownEntry } from '../MemoryBreakdownEntry/MemoryBreakdownEntry.ts' + +export interface MemoryMeasurement { + readonly breakdown?: readonly MemoryBreakdownEntry[] + readonly bytes: number +} diff --git a/packages/process-explorer-worker/src/parts/PerformanceWithMemory/PerformanceWithMemory.ts b/packages/process-explorer-worker/src/parts/PerformanceWithMemory/PerformanceWithMemory.ts new file mode 100644 index 0000000..d808f20 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/PerformanceWithMemory/PerformanceWithMemory.ts @@ -0,0 +1,5 @@ +import type { MemoryMeasurement } from '../MemoryMeasurement/MemoryMeasurement.ts' + +export interface PerformanceWithMemory extends Performance { + readonly measureUserAgentSpecificMemory?: () => Promise +} diff --git a/packages/process-explorer-worker/src/parts/SendMessagePortToProcessExplorer/SendMessagePortToProcessExplorer.ts b/packages/process-explorer-worker/src/parts/SendMessagePortToProcessExplorer/SendMessagePortToProcessExplorer.ts index 319cc1c..81b85c4 100644 --- a/packages/process-explorer-worker/src/parts/SendMessagePortToProcessExplorer/SendMessagePortToProcessExplorer.ts +++ b/packages/process-explorer-worker/src/parts/SendMessagePortToProcessExplorer/SendMessagePortToProcessExplorer.ts @@ -1,15 +1,7 @@ import { RendererWorker } from '@lvce-editor/rpc-registry' -interface RendererWorkerWithProcessExplorer { - readonly sendMessagePortToProcessExplorer: ( - port: MessagePort, - ) => Promise -} - export const sendMessagePortToProcessExplorer = async ( port: MessagePort, ): Promise => { - const rendererWorker = - RendererWorker as unknown as RendererWorkerWithProcessExplorer - await rendererWorker.sendMessagePortToProcessExplorer(port) + await RendererWorker.sendMessagePortToProcessExplorer(port) } diff --git a/packages/process-explorer-worker/src/parts/ToBreakdownProcess/ToBreakdownProcess.ts b/packages/process-explorer-worker/src/parts/ToBreakdownProcess/ToBreakdownProcess.ts new file mode 100644 index 0000000..8c08216 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/ToBreakdownProcess/ToBreakdownProcess.ts @@ -0,0 +1,19 @@ +import type { MemoryBreakdownEntry } from '../MemoryBreakdownEntry/MemoryBreakdownEntry.ts' +import type { ProcessInfo } from '../ProcessInfo/ProcessInfo.ts' +import * as GetBreakdownName from '../GetBreakdownName/GetBreakdownName.ts' +import * as WindowPid from '../WindowPid/WindowPid.ts' + +export const toBreakdownProcess = ( + entry: MemoryBreakdownEntry, + index: number, +): ProcessInfo => { + const name = GetBreakdownName.getBreakdownName(entry, index) + return { + cmd: name, + memory: entry.bytes, + name, + pid: -2 - index, + ppid: WindowPid.WindowPid, + synthetic: true, + } +} diff --git a/packages/process-explorer-worker/src/parts/WindowPid/WindowPid.ts b/packages/process-explorer-worker/src/parts/WindowPid/WindowPid.ts new file mode 100644 index 0000000..9c46ca6 --- /dev/null +++ b/packages/process-explorer-worker/src/parts/WindowPid/WindowPid.ts @@ -0,0 +1 @@ +export const WindowPid = -1