| 1593 | }> = [] |
| 1594 | |
| 1595 | export function getSlowOperations(): ReadonlyArray<{ |
| 1596 | operation: string |
| 1597 | durationMs: number |
| 1598 | timestamp: number |
| 1599 | }> { |
| 1600 | // Most common case: nothing tracked. Return a stable reference so the |
| 1601 | // caller's setState() can bail via Object.is instead of re-rendering at 2fps. |
| 1602 | if (STATE.slowOperations.length === 0) { |
| 1603 | return EMPTY_SLOW_OPERATIONS |
| 1604 | } |
| 1605 | const now = Date.now() |
| 1606 | // Only allocate a new array when something actually expired; otherwise keep |
| 1607 | // the reference stable across polls while ops are still fresh. |
| 1608 | if ( |
| 1609 | STATE.slowOperations.some(op => now - op.timestamp >= SLOW_OPERATION_TTL_MS) |
| 1610 | ) { |
| 1611 | STATE.slowOperations = STATE.slowOperations.filter( |
| 1612 | op => now - op.timestamp < SLOW_OPERATION_TTL_MS, |
| 1613 | ) |
| 1614 | if (STATE.slowOperations.length === 0) { |
| 1615 | return EMPTY_SLOW_OPERATIONS |
| 1616 | } |
| 1617 | } |
| 1618 | // Safe to return directly: addSlowOperation() reassigns STATE.slowOperations |
| 1619 | // before pushing, so the array held in React state is never mutated. |
| 1620 | return STATE.slowOperations |
| 1621 | } |
| 1622 | |
| 1623 | export function getMainThreadAgentType(): string | undefined { |
| 1624 | return STATE.mainThreadAgentType |