←back to thread

517 points bkolobara | 4 comments | | HN request time: 0.451s | source
Show context
merdaverse ◴[] No.45043051[source]
Code written below your line gets executed if you don't return early. More breaking news at 8.

Seriously, why would you think that assigning a value would stop your script from executing? Maybe the Typescript example is missing some context, but it seems like such a weird case to present as a "data race".

replies(8): >>45043245 #>>45043339 #>>45043398 #>>45043537 #>>45043876 #>>45046033 #>>45046975 #>>45049155 #
Arch-TK ◴[] No.45043398[source]
Assigning to `window.location.href` has a side effects. The side effect is that your browser will navigate to wherever you assigned, as if you had clicked a link. This is already a surprising behaviour, but given that this assignment is effectively loading a new page in-place, kind of like how `execve` does for a process, I can totally see how someone would think that JS execution would stop immediately after a link is clicked.

It's obviously not a good idea to rely on such assumptions when programming, and when you find yourself having such a hunch, you should generally stop and verify what the specification actually says. But in this case, the behaviour is weird, and all bets are off. I am not at all surprised that someone would fall for this.

replies(4): >>45043684 #>>45043902 #>>45044345 #>>45048334 #
1. stouset ◴[] No.45043684[source]
Part of the problem is that we unknowingly make a million little assumptions every day in the course of software development. Many of them are reasonable, some of them are technically unreasonable but fine in practice, and some of them are disasters waiting to happen. And it's genuinely hard to not only know which are which, but to notice even a fraction of them in the first place.

I'm sure I knew the href thing at one point. It's probably even in the documentation. But the API itself leaves a giant hole for this kind of misunderstanding, and it's almost certainly a mistake that a huge number of people have made. The more pieces of documentation we need to keep in our heads in order to avoid daily mistakes, the exponentially more likely it is we're going to make them anyway.

Good software engineering is, IMHO, about making things hard to hold the wrong way. Strong types, pure functions without side effects (when possible), immutable-by-default semantics, and other such practices can go a long way towards forming the basis of software that is hard to misuse.

replies(2): >>45049734 #>>45051440 #
2. buu700 ◴[] No.45049734[source]
Honestly, the href thing feels like a totally reasonable assumption to me. I think the API design is unfortunate, but given that the API is designed as it is, it stands to reason that the script would also halt execution upon hitting that line.

For me, that's exactly the kind of thing that I tend to be paranoid about and handle defensively by default. I couldn't have confidently told you before today what the precise behavior of setting location.href was without looking it up, but I can see that code I wrote years ago handled it correctly regardless, because it cost me nothing at the time to proactively throw in a return statement.

As in this example, defensiveness can often prevent frustrating heisenbugs. (Not just from false assumptions, but also due to correct assumptions that are later invalidated by third-party changes.) Even when technically unnecessary, it can still be a valid stylistic choice that improves readability by reducing ambiguity.

replies(1): >>45085111 #
3. gf000 ◴[] No.45051440[source]
This is actually mostly related to a language's expressivity, which can simultaneously be used for good and for obscure stuff. (Also, JS having a rough evolution from a badly designed scripting language with hacky injection points to the browser, to being an industrial language at the core of the modern web, with strong backwards compatibility)

This can be made into an extreme (e.g. C/Zig tries to make every line understandable locally - on the other extreme we have overloading any symbols, see Haskell/Scala).

4. phatskat ◴[] No.45085111[source]
> because it cost me nothing at the time to proactively throw in a return statement

This is how I’ve generally always handled redirects, be it server or client - if I’m redirecting the user somewhere else, my expectation is that nothing else on this page or in this script _should_ run. Will it? Maybe, JavaScript is weird. To avoid the possibility, I’m going to return instead of just hoping that my expectations are met.