-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
Expand file tree
/
Copy pathtimerify.js
More file actions
122 lines (104 loc) Β· 2.91 KB
/
timerify.js
File metadata and controls
122 lines (104 loc) Β· 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict';
const {
FunctionPrototypeBind,
MathCeil,
ObjectDefineProperties,
ReflectApply,
ReflectConstruct,
} = primordials;
const { createPerformanceNodeEntry } = require('internal/perf/performance_entry');
const { now } = require('internal/perf/utils');
const {
validateFunction,
validateObject,
} = require('internal/validators');
const {
isHistogram,
} = require('internal/histogram');
const {
codes: {
ERR_INVALID_ARG_TYPE,
},
} = require('internal/errors');
const {
enqueue,
} = require('internal/perf/observe');
const {
kEmptyObject,
} = require('internal/util');
function processComplete(name, start, args, histogram) {
const duration = now() - start;
if (histogram !== undefined)
histogram.record(MathCeil(duration * 1e6));
const entry =
createPerformanceNodeEntry(
name,
'function',
start,
duration,
args);
for (let n = 0; n < args.length; n++)
entry[n] = args[n];
enqueue(entry);
}
function onFulfilledTimerified(name, start, args, histogram, value) {
processComplete(name, start, args, histogram);
return value;
}
function timerify(fn, options = kEmptyObject) {
validateFunction(fn, 'fn');
validateObject(options, 'options');
const {
histogram,
} = options;
if (histogram !== undefined &&
(!isHistogram(histogram) || typeof histogram.record !== 'function')) {
throw new ERR_INVALID_ARG_TYPE(
'options.histogram',
'RecordableHistogram',
histogram);
}
function timerified(...args) {
const isConstructorCall = new.target !== undefined;
const start = now();
const result = isConstructorCall ?
ReflectConstruct(fn, args, fn) :
ReflectApply(fn, this, args);
if (!isConstructorCall && typeof result?.then === 'function') {
// Use `then` (not `finally`) so that a rejected thenable does NOT
// produce a performance entry or histogram record. This mirrors the
// behavior of synchronously-thrown errors, which never reach
// `processComplete`. Refs: https://github.com/nodejs/node/issues/42743
// Also, thenables are only required to implement `then`; relying on
// `finally` would break for minimal thenable implementations.
// Pass only an `onFulfilled` handler so any rejection propagates
// unchanged through the returned promise.
return result.then(
FunctionPrototypeBind(
onFulfilledTimerified,
result,
fn.name,
start,
args,
histogram));
}
processComplete(fn.name, start, args, histogram);
return result;
}
ObjectDefineProperties(timerified, {
length: {
__proto__: null,
configurable: false,
enumerable: true,
value: fn.length,
},
name: {
__proto__: null,
configurable: false,
enumerable: true,
value: `timerified ${fn.name}`,
},
});
return timerified;
}
module.exports = timerify;