1'use strict'; 2 3const { 4 FunctionPrototypeBind, 5 ObjectDefineProperties, 6 MathCeil, 7 ReflectApply, 8 ReflectConstruct, 9} = primordials; 10 11const { InternalPerformanceEntry } = require('internal/perf/performance_entry'); 12const { now } = require('internal/perf/utils'); 13 14const { 15 validateFunction, 16 validateObject, 17} = require('internal/validators'); 18 19const { 20 isHistogram, 21} = require('internal/histogram'); 22 23const { 24 codes: { 25 ERR_INVALID_ARG_TYPE, 26 }, 27} = require('internal/errors'); 28 29const { 30 enqueue, 31} = require('internal/perf/observe'); 32 33const { 34 kEmptyObject, 35} = require('internal/util'); 36 37function processComplete(name, start, args, histogram) { 38 const duration = now() - start; 39 if (histogram !== undefined) 40 histogram.record(MathCeil(duration * 1e6)); 41 const entry = 42 new InternalPerformanceEntry( 43 name, 44 'function', 45 start, 46 duration, 47 args); 48 49 for (let n = 0; n < args.length; n++) 50 entry[n] = args[n]; 51 52 enqueue(entry); 53} 54 55function timerify(fn, options = kEmptyObject) { 56 validateFunction(fn, 'fn'); 57 58 validateObject(options, 'options'); 59 const { 60 histogram, 61 } = options; 62 63 if (histogram !== undefined && 64 (!isHistogram(histogram) || typeof histogram.record !== 'function')) { 65 throw new ERR_INVALID_ARG_TYPE( 66 'options.histogram', 67 'RecordableHistogram', 68 histogram); 69 } 70 71 function timerified(...args) { 72 const isConstructorCall = new.target !== undefined; 73 const start = now(); 74 const result = isConstructorCall ? 75 ReflectConstruct(fn, args, fn) : 76 ReflectApply(fn, this, args); 77 if (!isConstructorCall && typeof result?.finally === 'function') { 78 return result.finally( 79 FunctionPrototypeBind( 80 processComplete, 81 result, 82 fn.name, 83 start, 84 args, 85 histogram)); 86 } 87 processComplete(fn.name, start, args, histogram); 88 return result; 89 } 90 91 ObjectDefineProperties(timerified, { 92 length: { 93 __proto__: null, 94 configurable: false, 95 enumerable: true, 96 value: fn.length, 97 }, 98 name: { 99 __proto__: null, 100 configurable: false, 101 enumerable: true, 102 value: `timerified ${fn.name}`, 103 }, 104 }); 105 106 return timerified; 107} 108 109module.exports = timerify; 110