|
1 | 1 | import { snapshot } from '../../server'; |
2 | 2 | import { STATE_SYMBOL } from '../constants'; |
3 | 3 |
|
4 | | -/** @type { Map<string, any> | null } */ |
| 4 | +/** @type { { label: string, time: number, sub: any, stack: string | void, value: any }[] | null } */ |
5 | 5 | export let tracing_expressions = null; |
6 | 6 | export let tracing_expression_reactive = false; |
7 | 7 |
|
8 | 8 | /** |
9 | | - * @template T |
10 | | - * @param {() => T} fn |
11 | | - * @param {string} label |
| 9 | + * @param {any} expressions |
12 | 10 | */ |
13 | | -export function log_traced_expressions(fn, label) { |
14 | | - var previously_tracing_expressions = tracing_expressions; |
15 | | - tracing_expressions = new Map(); |
16 | | - try { |
17 | | - var val = fn(); |
| 11 | +function log_expressions(expressions) { |
| 12 | + for (let expression of expressions) { |
| 13 | + const val = expression.value; |
| 14 | + const label = expression.label; |
| 15 | + const time = expression.time; |
18 | 16 |
|
19 | | - // eslint-disable-next-line no-console |
20 | | - console.group(`${label} (trace)`); |
21 | | - for (let [label, [val, stack]] of tracing_expressions) { |
| 17 | + if (time) { |
22 | 18 | // eslint-disable-next-line no-console |
23 | 19 | console.groupCollapsed( |
24 | | - label, |
| 20 | + `${label} %c${time.toFixed(2)}ms`, |
| 21 | + 'color: grey', |
25 | 22 | val && typeof val === 'object' && STATE_SYMBOL in val ? snapshot(val, true) : val |
26 | 23 | ); |
| 24 | + } else { |
27 | 25 | // eslint-disable-next-line no-console |
28 | | - console.log(stack); |
29 | | - // eslint-disable-next-line no-console |
30 | | - console.groupEnd(); |
| 26 | + console.groupCollapsed( |
| 27 | + label, |
| 28 | + val && typeof val === 'object' && STATE_SYMBOL in val ? snapshot(val, true) : val |
| 29 | + ); |
| 30 | + } |
| 31 | + |
| 32 | + if (expression.sub) { |
| 33 | + log_expressions(expression.sub); |
31 | 34 | } |
32 | 35 | // eslint-disable-next-line no-console |
| 36 | + console.log(expression.stack); |
| 37 | + // eslint-disable-next-line no-console |
| 38 | + console.groupEnd(); |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +/** |
| 43 | + * @template T |
| 44 | + * @param {() => T} fn |
| 45 | + * @param {string} label |
| 46 | + */ |
| 47 | +export function log_trace(fn, label) { |
| 48 | + var previously_tracing_expressions = tracing_expressions; |
| 49 | + try { |
| 50 | + tracing_expressions = []; |
| 51 | + |
| 52 | + var start = performance.now(); |
| 53 | + var value = fn(); |
| 54 | + var time = (performance.now() - start).toFixed(2); |
| 55 | + // eslint-disable-next-line no-console |
| 56 | + console.group(`${label} %c${time}ms`, 'color: grey'); |
| 57 | + log_expressions(tracing_expressions); |
| 58 | + // eslint-disable-next-line no-console |
33 | 59 | console.groupEnd(); |
34 | 60 |
|
35 | | - return val; |
36 | | - } finally { |
37 | 61 | if (previously_tracing_expressions !== null) { |
38 | | - for (let [label, entries] of tracing_expressions) { |
39 | | - if (!previously_tracing_expressions.has(label)) { |
40 | | - previously_tracing_expressions.set(label, entries); |
41 | | - } |
42 | | - } |
| 62 | + previously_tracing_expressions.push(...tracing_expressions); |
43 | 63 | } |
| 64 | + |
| 65 | + return value; |
| 66 | + } finally { |
44 | 67 | tracing_expressions = previously_tracing_expressions; |
45 | 68 | } |
46 | 69 | } |
47 | 70 |
|
48 | 71 | /** |
49 | 72 | * @template T |
50 | 73 | * @param {() => T} fn |
| 74 | + * @param {boolean} [call_expression] |
51 | 75 | * @param {string} label |
52 | 76 | */ |
53 | | -export function trace_expression(fn, label) { |
| 77 | +export function trace(fn, label, call_expression) { |
| 78 | + var previously_tracing_expressions = tracing_expressions; |
54 | 79 | var previously_tracing_expression_reactive = tracing_expression_reactive; |
| 80 | + |
55 | 81 | try { |
56 | 82 | tracing_expression_reactive = false; |
57 | | - var val = fn(); |
| 83 | + tracing_expressions = []; |
| 84 | + var value, |
| 85 | + time = 0; |
| 86 | + |
| 87 | + if (call_expression) { |
| 88 | + var start = performance.now(); |
| 89 | + value = fn(); |
| 90 | + time = (performance.now() - start); |
| 91 | + } else { |
| 92 | + value = fn(); |
| 93 | + } |
58 | 94 |
|
59 | | - if ( |
60 | | - tracing_expression_reactive && |
61 | | - tracing_expressions !== null && |
62 | | - !tracing_expressions.has(label) |
63 | | - ) { |
| 95 | + if (tracing_expressions !== null) { |
64 | 96 | // The Stack isn't as useful in FF and doesn't show sourcemaps |
65 | | - const stack = new Error().stack |
| 97 | + var stack = new Error().stack |
66 | 98 | ?.split('\n') |
67 | 99 | [/Firefox/.test(navigator.userAgent) ? 3 : 2].trimStart(); |
68 | | - tracing_expressions.set(label, [val, stack]); |
| 100 | + |
| 101 | + if (tracing_expression_reactive) { |
| 102 | + tracing_expressions.push({ label, value, time, stack, sub: null }); |
| 103 | + |
| 104 | + if (previously_tracing_expressions !== null) { |
| 105 | + previously_tracing_expressions.push(...tracing_expressions); |
| 106 | + } |
| 107 | + } else if (previously_tracing_expressions !== null) { |
| 108 | + previously_tracing_expressions.push({ |
| 109 | + label, |
| 110 | + value, |
| 111 | + time, |
| 112 | + stack, |
| 113 | + sub: tracing_expressions |
| 114 | + }); |
| 115 | + } |
69 | 116 | } |
70 | 117 |
|
71 | | - return val; |
| 118 | + return value; |
72 | 119 | } finally { |
| 120 | + tracing_expressions = previously_tracing_expressions; |
73 | 121 | tracing_expression_reactive = previously_tracing_expression_reactive; |
74 | 122 | } |
75 | 123 | } |
|
0 commit comments