Problem with type coercion and string concatenation in JavaScript in Greasemonkey script on Firefox

Posted by Yi Jiang on Stack Overflow See other posts from Stack Overflow or by Yi Jiang
Published on 2010-12-17T09:14:32Z Indexed on 2010/12/21 5:54 UTC
Read the original article Hit count: 350

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.

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about firefox