Woo! After a lot of testing, head-scratching and swearing, I found the problem! I wasn’t clearing the line dash mode correctly!
I had code like this:
if (typeof(dash) === "undefined")
dash = [1,0];
context.setLineDash(dash);
Visually, it does the right thing, draws a solid line. However I think it actually draws the line 1 pixel at a time instead!
The correct code is this:
if (typeof(dash) === "undefined")
dash = [];
context.setLineDash(dash);
Massive win!