I accidentally ran into what appears to be a very strange bug in Safari's javascript engine on iPad.
The unsigned shift operator >>> is supposed to bitwise right-shift a number. I experienced some errors in a script that worked fine on other platforms, stripped it down and ended up with this:
<html><head><script type='text/javascript'>
var one = 1;
function Zero()
{
return one*0;
}
function Strange()
{
return one = (Zero()+1) >>> 0;
}
var s = 'A bunch of ones: '; // except on iPad :(
for (var i=0; i<200; i++)
{
s += Strange()+' ';
}
document.write(s);
</script></head><body></body></html>
Live demo
Strangely enough, it correctly generates a bunch of ones, but at a certain point, something breaks and it only outputs zeroes from then on.
Obviously the >>> 0 is meaningless here (a shift over zero places typically does nothing, although it could have forced an integer to become unsigned if javascript made that distinction). It's just to demonstrate the problem, if you omit the >>> 0 it doesn't show up. In my actual situation there were different numbers and more complex expressions involved, but the same thing happened: everything works until a number of iterations, then something 'breaks' and variables suddenly become and remain zero, even after subsequent calculations that really ought to make them non-zero.
Works fine on Android and PC browsers. Strange huh?
The unsigned right shift operator ( >>> ) (zero-fill right shift) evaluates the left-hand operand as an unsigned number, and shifts the binary representation of that number by the number of bits, modulo 32, specified by the right-hand operand.
The left shift operator ( << ) shifts the first operand the specified number of bits, modulo 32, to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.
For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.
Zero-fill right shift (>>>) operator: The operator shifts the bits of the first operand by a number of bits specified by the second operand. The bits are shifted to the right and those excess bits are discarded, while 0 bit is added from left.
Not a "real" answer but perhaps a useful one, assuming (as seems VERY likely) that this is simply a bug in Apple's JIT compiler: This StackOverflow thread (Disabling JIT in Safari 6 to workaround severe Javascript JIT bugs) talks about how to disable the JIT on your code. Basically,
Wrap the offending statement in a do-nothing try-catch block.
I don't have an iOS device to test on, but does this make the problem go away? Can you apply the same kind of workaround to your original code?
function Strange()
{
try
{
return one = (Zero()+1) >>> 0;
}
catch (e) { throw e }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With