views:

100

answers:

5

I have the following code

if (msg.position == 0)
    //removed for brevity
else if (msg.position == txtArea.value.length)
    //removed for brevity
else {
    //ERROR: should not reach here.
    errorDivTag.innerHTML += msg.position + " " + txtArea.value.length;
}

I'm having some really weird situations where I'm getting the error in the last code block, but the printed positions show that msg.position is in fact equal to the txtArea.value.length. This only happens 1% of the time, almost as if I have some kind of race-condition in my code where the two are NOT equal during the second if statement, but equal when I print in the error message.

Any ideas?

+2  A: 

To start with, always use ===. That will prevent JavaScript from automatically coercing the types in the comparison, which means you'll be able to spot all sorts of bugs much more easily. In this case, it's possible you have some whitespace (which is basically impossible to see in the output) that is causing a string comparison instead of the (I assume) desired numeric comparison.

Also, I'm assuming you really meant to have { after your if and else if conditions. If not, that could be causing all sorts of strange behavior, depending on the code you removed due to brevity concerns. If you didn't, then you've got an extraneous } before your else condition.

UPDATE: Set a breakpoint in Firebug/DeveloperTools/DragonFly/whatever and inspect the values as the comparison occurs.

Hank Gay
I will use the '===' operator from now on, unfortunately it didn't solve the problem in this case. And in the case of brackets, I only have one line statement after the 'if' and 'elseif' blocks.
teehoo
Have you tried adding a variable to hold the value of `txtArea.value.length`? That should remove any concerns about the value changing between the comparison and the debug print.
Hank Gay
Wait, you only have one line (no braces) on your `if` and `else if`, but you have a closing brace before the last `else`? That seems like it could cause branching to happen differently than you expect. You might want to check that.
jhurshman
@Hank if this is the case, wouldn't this violate the javascript single threaded model?
teehoo
@jhurshman you're right, it was a typo in my example code, I updated/fixed the question.
teehoo
@teehoo I think it's unlikely to actually be a race condition for that very reason: JavaScript is essentially single-threaded. I'm just saying that using the debugger would (hopefully) provide the definitive answer as to what's going on.
Hank Gay
@Hank, Ok i'm going to choose this as the accepted answer even though I didnt solve the problem yet. But using the debugger should eventually lead me to find the problem :S.
teehoo
+1  A: 

Did you try changing the statement to...

parseInt(msg.position, 10) == txtArea.value.length
davydotcom
I have the code 'msg.position = parseInt(msg.position);' a little earlier before the code provided.
teehoo
@teehoo: You should also pass the `,10` parameter to `parseInt`, so the number isn't accidentally mistaken for an octal/hex number. (Without this parameter, IIRC a leading zero in the string will lead to the number being interpreted as octal.)
Lucas Jones
ok is any of this code getting called by a setTimeout Function at all? Thats really the only way a race condition may occur in javascript if at all.
davydotcom
@davydotcom This code is being called when an ajax request successfully returns. Does that qualify?
teehoo
+1  A: 

=== is more strict than == and is often useful. But this is the opposite problem as what you have here, where something looks equal, but isn't == or === (if something isn't ==, it will never be ===).

Is msg.position a String? Perhaps it contains a space or another similar character.

jhurshman
If it's a string, then `===` will reveal that fact. That's my favorite benefit of using it.
Hank Gay
msg.position is being cast using 'msg.position = parseInt(msg.position, 10);' before the example code.
teehoo
+2  A: 

If you use

parseInt(msg.position)

without a radix, you will run into problems with 08 and 09, because they are parsed as octal numbers and giving NaN. Always use a radix:

parseInt(msg.position, 10)
Magnar
I never knew this. Doesn't help in this case though.
teehoo
+1  A: 

I had this problem today with a checksum value in one of my js modules. A test was showing that two values were not equal, yet printing the values showed they were equal.

Ran it in the debugger and (re-)discovered that integer types in Javascript are 64-bit floating quantities. One of the numbers was displaying as negative in the debugger - exactly (0xFFFFFFFF+1) less than the other number. Somehow when printed, they displayed as exactly the same.

I was using a custom routine to format them in hex, which probably had something to do with it. That combination of circumstances seems unlikely in your case though.

I discovered the sign issue in my code by computing the delta between the numbers, and displaying that. It showed up as MAX_UINT32 + 1, which reminded me that these numbers are really 64-bit floats.

Cheeso