diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index 34d2a58bd017c1..6d98a26896d809 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -232,7 +232,9 @@ changes: to time async functions. --> -* `fn` {Function} +* `fn` {Function} Only accept function and class. If the fn is a function( +includes "old style" class) will be executed directly or will be executed +by the `new` operator. * `options` {Object} * `histogram` {RecordableHistogram} A histogram object created using `perf_hooks.createHistogram()` that will record runtime durations in diff --git a/lib/internal/perf/timerify.js b/lib/internal/perf/timerify.js index dae0b06bf80c8a..c9862edee68707 100644 --- a/lib/internal/perf/timerify.js +++ b/lib/internal/perf/timerify.js @@ -21,10 +21,6 @@ const { isHistogram } = require('internal/histogram'); -const { - isConstructor, -} = internalBinding('util'); - const { codes: { ERR_INVALID_ARG_TYPE, @@ -73,13 +69,14 @@ function timerify(fn, options = {}) { if (fn[kTimerified]) return fn[kTimerified]; - const constructor = isConstructor(fn); + // If the parameter is a function and it will be called directly + // or used as `new` operator. + const isCalledAsConstructor = (fn) => /^\s*class/.test(fn.toString()); function timerified(...args) { const start = now(); - const result = constructor ? - ReflectConstruct(fn, args, fn) : - ReflectApply(fn, this, args); + const result = isCalledAsConstructor(fn) ? + ReflectConstruct(fn, args, fn) : ReflectApply(fn, this, args); if (!constructor && typeof result?.finally === 'function') { return result.finally( FunctionPrototypeBind( diff --git a/src/node_util.cc b/src/node_util.cc index 2db45bd1fb40af..5b5dab36f08fbf 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -289,11 +289,6 @@ static void GuessHandleType(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(OneByteString(env->isolate(), type)); } -static void IsConstructor(const FunctionCallbackInfo& args) { - CHECK(args[0]->IsFunction()); - args.GetReturnValue().Set(args[0].As()->IsConstructor()); -} - static void ToUSVString(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK_GE(args.Length(), 2); @@ -344,7 +339,6 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(WeakReference::IncRef); registry->Register(WeakReference::DecRef); registry->Register(GuessHandleType); - registry->Register(IsConstructor); registry->Register(ToUSVString); } @@ -384,7 +378,6 @@ void Initialize(Local target, env->SetMethodNoSideEffect(target, "getConstructorName", GetConstructorName); env->SetMethodNoSideEffect(target, "getExternalValue", GetExternalValue); env->SetMethod(target, "sleep", Sleep); - env->SetMethodNoSideEffect(target, "isConstructor", IsConstructor); env->SetMethod(target, "arrayBufferViewHasBuffer", ArrayBufferViewHasBuffer); Local constants = Object::New(env->isolate()); diff --git a/test/parallel/test-performance-function.js b/test/parallel/test-performance-function.js index ea928028208e47..2f6b8e2ef59802 100644 --- a/test/parallel/test-performance-function.js +++ b/test/parallel/test-performance-function.js @@ -13,6 +13,30 @@ const { setTimeout: sleep } = require('timers/promises'); +{ + const perf = performance.timerify(function foo() { + let sum = 0; + for (let i = 0; i < 101; i++) { + sum += i; + } + return sum; + }); + const result = perf(); + assert.strictEqual(result, 5050); +} + +{ + class Foo { + constructor() { + /* eslint-disable no-constructor-return */ + return Promise.resolve('foo'); + } + } + const perf = performance.timerify(Foo); + const result = perf(); + result.then(common.mustCall((val) => assert.strictEqual(val, 'foo'))); +} + { // Intentional non-op. Do not wrap in common.mustCall(); const n = performance.timerify(function noop() {});