Tuesday, May 23, 2006

Javascript bug - when an object is not an object

I ran into another Javascript bug the other day. The code read as follows:

...
MyObject.isActive.activeSlider.setValue(pos);   Eq (1)
...


This looks fine, but MyObject.isActive is one of those funny typeless Javascript beasts that mutate at the drop of a hat. In some cases it is a boolean, set like this:

...
MyObject.isActive = true;
...


In other cases it is an object with properties like activeSlider.

So what happens when MyObject.isActive is currently a boolean and Eq (1) is called? Nothing. Alarms and whistles should go off, but no - nada, bupkis.

Well, the situation was more complicated than that. Equation (1) was being evaluated from within a Javascript function that had been called by a Java applet embedded in the page. An instance of netscape.javascript.JSObject was used to call the Javascript method. And a netscape.javascript.JSException was being raised, and caught; that was visible in the Java console of my Firefox browser where the stacktrace was printed out.

But there was nothing in the Javascript console (at least, not in my version of the console). Maybe this all makes perfect sense. I haven't checked to see if an uncaught Exception in the applet appears as an error in the Javascript console (I should really do this). Maybe it's a bad idea to catch Exceptions thrown by the JSObject...

In any case, I had a hell of a time debugging this one. When I finally located the error, I added a conditional to the Javascript to verify that the property and its method exist before calling them:

...
if (MyObject.isActive &&
  MyObject.isActive.activeSlider &&
  MyObject.isActive.activeSlider.setValue) {
    MyObject.isActive.activeSlider.setValue(pos);
...
}


Oh yes, the problem is gone! And no, I did not write that Javascript...

The equals/assignment bug

I recently found a classic bug in some Javascript code (not my code!):

if (MyObject.isActive = this) {
...
}


Of course, the code should be

if (MyObject.isActive == this) {
...
}


This kind of bug is a real joy to hunt down ;-)

I learned years ago to write the condition in the anti-assignment way. For example, instead of writing
if (x == 3) {...,
write it
if (3 == x) {...
where possible, because the assignment error (using one "=" instead of two) should be caught by the compiler/interpreter in the latter case. I do my best to hold to this, and it has saved me some headaches.

In this case, if you write

if (this = MyObject.isActive) {
...
}

you see the error in the Javascript console - "Error: invalid assignment left-hand side".

Wednesday, May 10, 2006

How to remove a trusted applet

I'm testing a self-signed Java applet. When I first loaded a page containing the applet into Firefox, I got the usual message about whether or not to trust the publisher of the applet ("The application's digital signature is invalid..."). I checked the box to "Always trust content from this publisher...", because I didn't want to be faced with that message every time I hit the page.

Today I wanted to test the process as it would appear to a new user, so I really needed to "untrust" that applet... revoke its privileges... remove its certificate... not sure of the correct terminology. Which is probably why it took me so long to find out how to do this. Firefox has a "Certificate Manager", but I couldn't find the digital signature in there anywhere, that's not the answer (FYI, the Firefox certificate manager is under Tools -> Options -> Advanced -> Manage Certificates).

It turns out that if you want to revoke your trust in an applet that you've agreed to always trust, you have to use the Java Control Panel. This tool is found in the jre/bin directory. This is the same directory that contains java.exe, keytool.exe, etc if you are in Windows. For example, it may be here:

C:\Program Files\Java\jre1.5.0_06\bin\javacpl.exe

When you run javacpl.exe, go to the Security panel and click on the Certificates button. You should see the Certificate for your applet there. You can delete it, and then when you load your web page, you should get the popup security warning again.