What could be wrong?

Getters and setters as debugging shortcuts

Webcompat.com’s issue 1449 was a fun little challenge this morning. So the site thetiebar.com runs some JavaScript to adapt to the device’s screen size and resolution. One of the things it does is to select images that fit the available space.

This is not a bad idea - the problem is that in Firefox on Android, it tends to end up with an enlarged 24px wide image, which looks rather poor. Certainly doesn’t look like a tie you might want to buy.

Image of a tie poorly rendered on thetiebar.com

So what is taking place here, and is it the site’s or Firefox’s fault?

We knew the generated markup was basically like this:

    <img class="tbs-slider-img" 

so the likely challenge is simply to find and review the script that reads the data-retina attribute and replaces the w=auto part with an actual measurement.

Easy? Not quite. Obvious shortcuts like searching for “retina” didn’t find interesting code. Some of the JavaScript was “packed” in rather obfuscated ways, but still.. surprising how hard it was to find this stuff. Keywords like src, w or auto are too common and useless for search fodder.

Now, we know the code we want to look at sets src on an image. What if we can just add a breakpoint when .src is set?

I used a HTTP debugging proxy to insert a SCRIPT element with this code at the top of the main page before it was sent to the browser:

    HTMLImageElement.prototype.__defineSetter__('src', function(val){debugger;});

And voila - during loading it hits the debugger statement a few times, first for images with ?h=auto and then finally for some with ?w=auto.

(If you’re curious, the problem is that the JavaScript makes the assumption that an image element with greater than zero width is filling the available space, while Firefox makes the image element take up 24px by default - perhaps for alt text or an error icon or something?)

Such getters and setters tricks can be excellent shortcuts when you need to find a specific part of a foreign code base. You can even define a non-enumerable getter or setter that can trigger a breakpoint when a named property is set on any object defined by a site. Here’s one I used for debugging another really complex issue recently:

        {enumerable:false, set: function(value){ 

This lets the debugger break on code like

    var obj = {};
    obj.top = '-20px';

So if you’re looking for somewhere a specific property is being set to a characteristic value, you now know the fastest way to get there in your JavaScript debugger.

Console.log()ing developer needs

2016-06-10 / Found code

Certain sites that want to hire developers have found a clever recruitment approach: add “we’re hiring” in the site’s source and/or console.log() output. I’m pretty sure I first saw this on yahoo.com several years ago. A number of other sites also seem to vainly believe that good developers want to read their source code…

Then there are sites doing this:

Screenshot of console with a 'we are hiring' message and security warnings.

A cheery “we’re hiring” - followed by a bunch of security warnings. You know, since you’re hiring - perhaps start with a security consultant?

Firefox devtools - non-intrusive way to add debug code

2016-06-09 / Developer tools, Mozilla

The other day, I was working on a rather complex bug on wunderground.com. This site overlays a weather radar animation on top of a Google Maps-based map.

The problem was that when the animation has been left open for a while, one of the “frames” of the animation will be stuck in the first state from whenever you opened the map.

The site renders radar data with layers of 256x256 px big CANVAS elements, about 6x6 elements in each layer. Layers are hidden with opacity:0 and one at a time is shown from an interval.

There’s a lot of JavaScript (including of course the Google maps API scripts and ads), in various stages of compression and obfuscation.

Since my first attempt at understanding the architecture was looking at the DOM in the inspector I spent quite some time digging around among the hundreds of CANVAS elements trying to figure out how they were used and which ones were part of the layer with outdated data.

Eventually I realised that the site loads radar graphic PNG URLs with embedded timestamp and coordinate data, like this one (where the ‘66’ and ‘94’ have something to do with coordinates of the square in a grid):


These images are painted into the corresponding CANVAS elements.

Each 6 minutes, the site decides to load a new set of graphics. While doing so, it will destroy all existing CANVAS tiles to re-add and repaint them. This quirk made for a rather annoying debugging experience - every once in a while when I was digging around in the DOM the whole thing would get reset. If I had added properties or IDs to CANVAS elements and their parents to be able to locate them more easily, those would go away too.

Searching for “radar” in the JavaScript debugger was a lucky shortcut to wundermap.min.js - quite a lot of code there seemed relevant. Also, there are fragments of debug code in the source:

Screenshot of code with a p._debug if statement highlighted

Within the JavaScript debugger in Firefox devtools, you can’t edit this code. But there’s a neat hack that lets you switch this._debug to true in this source anyway: add a conditional breakpoint that does it. Code to evaluate the condition of a conditional breakpoint will run in the scope of that line. Here’s an animation of how I triggered the site’s CanvasMapType debug code - the void() statement will return undefined and make sure the debugger does not stop at the breakpoint, and p is a reference to this:

Animation of adding a conditional breakpoint setting p._debug to true

Further down in the same method, it’s evident that enabling debugging will add some more information to the DOM. What I’m most interested in here is what URLs are used to paint each CANVAS element. There’s an l variable which refers to the URL - what if I set another conditional breakpoint just after the line where the site added its own debug data to the page? void(b.innerHTML += ‘ ‘ + l) might do:

Screenshot of debugger with a breakpoint whose condition sets innerHTML

This let me see the URLs that were used for each CANVAS element right there in the page itself:

Screenshot of site when the debug code has changed the rendering

And this led to the breakthrough: the URLs shown for the CANVAS elements that “jump back in time” have a different format than the others. These URLs do not have embedded timestamp data - they look like this: radartiles-ak4.wxug.com/tiles/8/66/94.png

My guess is that these images without any embedded time stamp are supposed to get the “current” state of things. If the browser decides to cache and not revalidate those images, the old graphics will be painted into the CANVAS elements when the JavaScript wants to show “now” state.

The site seems to leave such caching decisions up to the browser - it sends Last-Modified and ETag, but no Cache-Control. I am no expert on the caching side of HTTP though. Perhaps we should revalidate each time the URL is required? Perhaps not? At least now we know why it happens - and can draw a few lessons for debugging too:

  • It can be surprisingly useful to trigger inert debug code in websites. Several years ago, I had a hack replacing all instances of //\salert/( with just “alert(“ on all sites, and it could be quite entertaining
  • Avoid trying to inspect 500 CANVAS elements unless you really have to..
  • Using conditional breakpoints to “inject” code and change script behaviour can be very useful

If you didn’t know about this trick yet, I hope you’ll start using it and find it useful.

Debugging sites in Firefox Android

2016-05-16 / Firefox Android

WebIDE helps debugging web pages in Firefox on Android, but I’ve been missing simple ways to inject code that can help me debug issues. Debugging can be very time consuming, and one is always looking for shortcuts. If it’s possible to throw in a script that, say, throws whenever IFRAME.src is set it can allow me to zoom in on a method I need to find.

In Presto-based Opera, the User JavaScript API was an excellent debugging aid, as was the “Refresh from cache” command. Good, old days. Well, I’ve been exploring ways to inject debug code and find similar shortcuts in Firefox on Android, and here’s an addon that promises enabling similar stuff. See the readme for details.

(It’s admittedly a little more painful that it should be to keep editing/removing/re-installing the addon - for now - so it should probably be rewritten to just read “patch” files from the file system and evaluate them inside the page - or something. That way, just adb push-ing a file to the phone would change the debug output. Maybe someone can help implementing that?)

Bug safari w18/2016

It took me quite a while to find the actual problem in Webcompat 2406. It turns out to be a nice reminder that the world isn’t black and white: it takes two to tango, and here the JavaScript author makes one mistake (forgets listing all his Ext requirements) and Firefox another (doesn’t suppress script onload during sync XHR). Things that could be better on both sides. Keep fixing things..