Problem with type coercion and string concatenation in JavaScript in Greasemonkey script on Firefox
- by Yi Jiang
I'm creating a GreaseMonkey script to improve the user interface of the 10k tools Stack Overflow uses. I have encountered an unreproducible and frankly bizarre problem that has confounded me and the others in the JavaScript room on SO Chat. We have yet to find the cause after several lengthy debugging sessions.
The problematic script can be found here. Source - Install
The problem occurs at line 85, the line after the 'vodoo' comment:
return (t + ' (' + +(+f.offensive + +f.spam) + ')');
It might look a little weird, but the + in front of the two variables and the inner bracket is for type coercion, the inner middle + is for addition, and the other ones are for concatenation.
Nothing special, but observant reader might note that type coercion on the inner bracket is unnecessary, since both are already type coerced to numbers, and type coercing result is useless when they get concatenated into a string anyway. Not so! Removing the + breaks the script, causing f.offensive and f.spam to be concatenated instead of added together.
Adding further console.log only makes things more confusing:
console.log(f.offensive + f.spam); // 50
console.log('' + (+f.offensive + +f.spam)); // 5, but returning this yields 50 somehow
console.log('' + (+f.offensive + +f.spam) + ''); // 50
Source: http://chat.stackoverflow.com/transcript/message/203261#203261
The problem is that this is unreproducible - running scripts like
console.log('a' + (+'3' + +'1') + 'b');
in the Firebug console yields the correct result, as does
(function(){
return 'a' + (+'3' + +'1') + 'b';
})();
Even pulling out large chunks of the code and running them in the console does not reproduce this bug:
$('.post-menu a[id^=flag-post-]').each(function(){
var f = {offensive: '4', spam: '1'};
if(f){
$(this).text(function(i, t){
// Vodoo - please do not remove the '+' in front of the inner bracket
return (t + ' (' + +(+f.offensive + +f.spam) + ')');
});
}
});
Tim Stone in the chatroom has reproduction instruction for those who are below 10k.
This bug only appears in Firefox - Chrome does not appear to exhibit this problem, leading me to believe that this may be a problem with either Firefox's JavaScript engine, or the Greasemonkey add-on. Am I right?
I can be found in the JavaScript room if you want more detail and/or want to discuss this.