-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Open
Labels
Design NotesNotes from our design meetingsNotes from our design meetings
Description
Function Expression Callback Analysis and deferred
- Story of adding
/** @deferred */to the Node.js.d.tsfiles node: Add deferred tag for ts5.6 DefinitelyTyped/DefinitelyTyped#70084- Mostly from @sandersn's perspective.
- Asked: Is this only on parameters?
- Yes.
- Easy to add
/** @deferred */incorrectly to paramerters it doesn't really apply to. Silently does nothing.- Maybe fine?
- Has to be exactly where the parameter is. Can't do it like
@deferred @param {number} x */ - 80% of the time,
deferredneeds to be added because a function is asynchronously called. - Had to ask: does "not guaranteed to be called"
deferred?- Not necessarily.
- Kind of a tripping point though.
deferredhad to be sprinkled over so many signatures in Node.js.- Could use
listeneras a heuristic to figure out where to put it.
- Could use
- Is assuming possibly-called and needing to annotated with
deferredthe right default?- So
deferredvs.immediate. - In favor of possibly-called default.
- Collection (array, map, set) callbacks never are
deferred. Assuming possibly-called favors APIs like this. - Better to be more conservative on control flow analysis.
- Collection (array, map, set) callbacks never are
- In favor of deferred by default.
- Breaks existing code more.
- All asynchronous API callbacks (event handlers, I/O, timers) are deferred functions.
immediatemight actually be inferrable!
- So
- If we started things from scratch, it feels like
deferredwould be the right choice.- Have to assume lots of people have
.d.tsfiles outside of their control - the only workaround is to-
update the
d.tsor (very challenging for a lot of devs to be honest) or -
define a function like
function deferred<T extends (...args: any[]) => any>(deferred fn: T): T { return fn; }
and pepper
deferred(...)calls around each callback that has an issue.- But the callbacks don't error, subsequent references to a variable error. Users are likely to just cast instead.
-
- If this was behind
--strictit would be an easier sell for many many call-sites in an update. - Hard to get a sense without running on bigger codebases.
- Have to assume lots of people have
- With this PR, we are generally misunderstanding more code. Doesn't seem to catch as many bugs as we would think. It does error on idiomatic code like doing some async cleanup, but using to a variable afterwards
- Swapping the default behavior is quite surprising. It's probably a better default, but is it breaks for the sake of breaks?
- What are the conclusions and next steps?
- We don't feel comfortable merging for 5.6.
- We do want to review the breaks.
- Ask for feedback from partner teams - can they adopt this? Are they catching bugs?
Metadata
Metadata
Assignees
Labels
Design NotesNotes from our design meetingsNotes from our design meetings