That's because of the g flag. If you invert the two calls, you'll get different results because the global flag sets pattern.lastIndex and starts matching from that index the next time you call .test/.exec. When inverting the calls, you'd get a non-null result for .exec, and false for .test.
With .lastIndex and the global flag, in your case it matches the URL for .test, and will start looking for more URLs after the first URL when you execute .exec. There are no more URLs, so you'll get null. Note that lastIndex is then reset to 0, so calling .exec again would work.
Anyhow, you seem to be looking for str.match(pattern) instead, which simply lists all matches:
var str = " test http://example.dom.com/-6/x_5eb0916a.jpg"
+ " \nfoo http://example2.com/test.png";
var pattern = /(http:\/\/\S+\.(?:jpg|gif|png|jpeg|JPG|GIF|PNG|JPEG))/gm;
str.match(pattern);
// ["http://example.dom.com/-6/x_5eb0916a.jpg", "http://example2.com/test.png"]
)too much at the end of line 2. Also what isstr? It's undefined in your code.\/between your domain and file extension patterns, to prevent subdomains from being parsed otherwisehttp://some.png.example.com/home.htmlwill give youhttp://some.png(I concede it's just a matter of principle ;) ).