You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is adapted from #5495 which was closed with Issue Bankruptcy before receiving a reply. This issue is still a problem in the latest versions of lodash.
Background
debounce and throttle take optional options objects:
The options dangerously get set to unexpected values.
For debounce:
✅ leading falls back to false
❗ maxWait falls back to 0
❗ trailing falls back to false
For throttle:
❗ leading falls back to false
❗ trailing falls back to false
Cause
The cause of this behavior is that the code is checking for settings using the in operator. Instead of 'property' in options, a much better check would be options.property !== undefined.
In JavaScript, we nearly always treat missing properties and undefined properties as the same thing. Even though this is not technically true because an object can have a property with an ndefined` value, it's very surprising when code doesn't do this.
While explicitly calling these functions with explicitly undefined properties is probably very uncommon, it's not uncommon at all to implicitly do so. For example, if a function is wrapping throttle to vend its behavior, one can easily see how this could happen and cause very subtle and unexpected bugs.
Example Use Case
This example is adapted from @k-funk's example in #4973, where a React hook is extending debounce:
functionuseDebounce(fn,delay,{ leading, trailing, maxWait }): {// unrelated setup codeconstfnRef=useRef(fn)useLayoutEffect(()=>fnRef.current=fn,[fn])returnuseMemo(// ❗ Note the subtle bug here - leading, trailing, and maxWait could all be set incorrectly!()=>debounce(()=>fnRef.current(),delay,{ leading, trailing, maxWait }),[leading,trailing,maxWait]))
This issue is adapted from #5495 which was closed with
Issue Bankruptcy
before receiving a reply. This issue is still a problem in the latest versions oflodash
.Background
debounce
andthrottle
take optionaloptions
objects:For debounce:
lodash/lodash.js
Lines 10278 to 10282 in ddfd9b1
For throttle:
lodash/lodash.js
Lines 10879 to 10883 in ddfd9b1
Notice that each of these options has sensible defaults.
Bug
If you set these properties to
undefined
rather than leaving them out of the object, for example:The options dangerously get set to unexpected values.
For debounce:
leading
falls back tofalse
maxWait
falls back to0
trailing
falls back tofalse
For throttle:
leading
falls back tofalse
trailing
falls back tofalse
Cause
The cause of this behavior is that the code is checking for settings using the
in
operator. Instead of'property' in options
, a much better check would beoptions.property !== undefined
.The buggy code is here:
Debounce:
lodash/lodash.js
Lines 10320 to 10325 in ddfd9b1
Throttle:
lodash/lodash.js
Lines 10904 to 10907 in ddfd9b1
Expected Behavior
In JavaScript, we nearly always treat missing properties and
undefined
properties as the same thing. Even though this is not technically true because an object can have a property with an ndefined` value, it's very surprising when code doesn't do this.While explicitly calling these functions with explicitly
undefined
properties is probably very uncommon, it's not uncommon at all to implicitly do so. For example, if a function is wrappingthrottle
to vend its behavior, one can easily see how this could happen and cause very subtle and unexpected bugs.Example Use Case
This example is adapted from @k-funk's example in #4973, where a React hook is extending
debounce
:Related Issues
Potentially related:
_.throttle
'swait
not guaranteed in special case #4650The text was updated successfully, but these errors were encountered: