-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf_hooks: fix timerify bug #42883
base: main
Are you sure you want to change the base?
perf_hooks: fix timerify bug #42883
Conversation
I've fixed the issue |
could you please add a test case for this? |
if (!constructor && typeof result?.finally === 'function') { | ||
return result.finally( | ||
if (!constructor && typeof result?.then === 'function') { | ||
return result.then( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we retrieve result.then
twice which theoretically not work like JS spec strictly. We'd better write a helper to ensure such subtle semantic. (Not sure whether Node.js already have such internal thenable helpers).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean like this?
Lines 763 to 771 in 1e76165
function checkIsPromise(obj) { | |
// Accept native ES6 promises and promises that are implemented in a similar | |
// way. Do not accept thenables that use a function as `obj` and that have no | |
// `catch` handler. | |
return isPromise(obj) || | |
(obj !== null && typeof obj === 'object' && | |
typeof obj.then === 'function' && | |
typeof obj.catch === 'function'); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, if follow JS spec strictly, the code should be:
const {then} = result
if (typeof then === 'function') {
ReflectApply(then, result, [callback])
}
Because theoretically result.then
could be a getter, and two retrieve could give u different result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't understand why checkIsPromise
"do not accept thenables that use a function as obj
and that have no catch
handler" intentionally, this limitation seems wrong to me.
9dc34fa
to
da9e49a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, we need to edit the document
Lines 336 to 338 in 7a53696
If the wrapped function returns a promise, a finally handler will be attached | |
to the promise and the duration will be reported once the finally handler is | |
invoked. |
if (!constructor && typeof result?.then === 'function') { | ||
return result.then( | ||
function wrappedTimerifiedPromise(value) { | ||
processComplete(fn.name, start, args, histogram); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One idea which is not relate to the bug directly, but:
currently, now
is called in the processComplete
(duration = now() - start
) , but consider the goal is to calc the time as precise as possible, it may be better to calc it outside like:
const t = now()
processComplete(fn.name, start - t, args, histogram)
(also need to modify other related places, omit here)
This could rule out the invoking time of processComplete
, in the cases of microbenchmark, such cost can't be ignored.
Fixes: #42743