Skip to content
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

Update parseInterval to handle "0" correctly #1835

Merged
merged 6 commits into from
Dec 20, 2023

Conversation

tncowart
Copy link
Contributor

When a parameter like "0ms" is passed in to parseInterval it gets parsed to 0. Previously this would result in a return value of "undefined" because 0 is falsy and thus the return 0 || undefined statements return undefined.

The purpose of the form parseFloat(str) || undefined was to return "undefined" if parseFloat failed (parseFloat returns NaN, a falsy value, if it can't parse its argument). Unfortunately, as mentioned, parseFloat can also succeed and return a falsy value -- when the argument is "0" (or "0.0", etc.). So the new code, rather than depending on the falsiness of the result of parseFloat, explicitly checks for a NaN.

When a parameter like "0ms" is passed in to parseInterval it gets parsed to 0.
Previously this would result in a return value of "undefined" because 0 is falsy
and thus the `return 0 || undefined` statements return undefined.

The purpose of the form `parseFloat(str) || undefined` was to return "undefined" if
parseFloat failed (parseFloat returns NaN, a falsy value, if it can't parse its
argument). Unfortunately, as mentioned, parseFloat can also succeed and return a
falsy value -- when the argument is "0" (or "0.0", etc.). So the new code, rather
than depending on the falsiness of the result of parseFloat, explicitly checks for
a NaN.
Adds some semicolons to parseInterval (and tests) for consistency.
Adds test test to make sure parseInterval works on "0".
@Telroshan Telroshan added the bug Something isn't working label Sep 27, 2023
@Telroshan
Copy link
Collaborator

Good catch! Falsy checks indeed become an issue when 0 is an acceptable value
To expand on this, while I don't know when you would need a 0 interval (which would be so spammy), it is an accepable value as per the setInterval doc, thus should be handled properly as this PR suggest

delay Optional
Defaults to 0 if not specified.

@Telroshan Telroshan added ready for review Issues that are ready to be considered for merging and removed ready for review Issues that are ready to be considered for merging labels Sep 27, 2023
@Telroshan
Copy link
Collaborator

Now that I think about it @tncowart
I see at least one other falsy check usage in the code on the retrieved value from setInterval, that was not modified in this PR.

Could you add tests with 0 values to make sure this actually fixes the end behavior?
Also note that this applies to every, throttle and delay keywords, as well as swapDelay and settleDelay, so there are a few features impacted.

Internally, htmx uses setTimeout, which also accepts the 0 value, and would benefit from this PR. Just gotta make sure it works as expected and fixing the parseInterval function alone resolves the issue (right now I think other falsy checks in the code will counter this)

@Telroshan Telroshan added the needs test PR needs a test label Sep 27, 2023
@tncowart
Copy link
Contributor Author

@Telroshan Do I need to update tests in both test and www/static/test ? What is the difference?

@Telroshan
Copy link
Collaborator

@tncowart The www directory is the htmx website's code, and we automatically copy the tests to it on new release so that the tests are runnable on the public website.
You may ignore them and should only update the files in the test directory
Hope this helps!

@tncowart
Copy link
Contributor Author

@Telroshan Are these sufficient? I also updated one of the falsy conditionals in htmx.js.

@Telroshan
Copy link
Collaborator

Thanks a lot for the tests @tncowart!
Looking at the core, I think there are a few more places with falsy checks that should probably also be addressed (linking to the corresponding line of code for each of the following)

These values come from user settings that are read from parseInterval,
so they could be a number or undefined.

If the value being checked is > 0 setTimeout will be called with some
associated function. If the value is 0 or 'undefined' the associated function
will be called immediately ('undefined' is not greater than 0).
Copy link
Collaborator

@Telroshan Telroshan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a7c9bcd

Why not use the !== undefined check here as you did for the pollInterval?
As per the setTimeout doc,

delay
If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, the next event cycle.

So having a delay of 0 is not the same as calling the function right away, as it'll in fact execute in the next cycle
Let me know if I'm missing something there!

@tncowart
Copy link
Contributor Author

I think checking for x > 0 keeps the same behavior as before (0 and undefined are both false), whereas checking for x !== undefined subtly changes the behavior (only undefined is false). So maybe I should do > 0 everywhere, instead of !== undefined. Does that sound right -- change the !== undefined test to > 0?

@Telroshan
Copy link
Collaborator

Oh you're right, it could be a breaking change as what was formerly called immediately would suddenly be delayed to the next cycle

I see that the default swap delay is set to 0 in the default config, so it would impact all existing apps using htmx, forget that!

`pollInterval !== undefined` is a subtly different conditional than just `pollInterval` or `pollInterval > 0` (which are equivalent). Changes the conditional to `pollInterval > 0` so as to not change the behavior but also be more explicit in the test.
@alexpetros alexpetros added ready for review Issues that are ready to be considered for merging and removed needs test PR needs a test labels Dec 20, 2023
@1cg 1cg merged commit 078d5da into bigskysoftware:dev Dec 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working ready for review Issues that are ready to be considered for merging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants