MooTools setOptions() nullifies object references

I bumped up into a problem where the object references where resolved as object copies when I passed them to class instances. That might sound easy to resolve, but unfortunately I was already deep in code and it was difficult to see this. Therefore, here’s a little explanation for those who are facing the same frustrating issue.

Say, you have variable ‘a’ and you want to pass it to a MooTools class B instance during creation. In the easiest case you’d use new B({ myReference: a}) and trust on MooTools’ Class.setOptions() to minify the need of code lines. This is what you should do… well at least that’s what I did and in this case it was a mistake.

It turns out that Class.setOptions() merges it’s arguments to this.options and then takes copy of them via $merge(). That means that any variable references you pass to setOptions() will get copied to this.options and.. well, that’s it. See lines 1170-1173 in uncompressed version of MooTools 1.2:

var Options = new Class({
    setOptions: function(){
        this.options = $merge.run([this.options].extend(arguments));

That effectively nullifies the benefits of Class.setOptions() if you want to pass in variable references..

Here’s a longer example to clarify (use Firebug):

  // The most basic MooTools class that implements options
  // ref is a variable meant for pointing at given object
  // (won't do that, however)
  var B = new Class({
    Implements: Options,
    options: {
      ref: null
    },
    initialize: function(options) {
      this.setOptions(options);
    }
  });

  // Ok let's create an instance that we can pass to B
  // It's similar with all sorts of variables
  var A = new Class({
    initialize: function() {
      this.somevar = 'untouched';
    }
  });
  var a = new A();
  
  // Create an instance of B and give it somevar as reference
  var b = new B({ ref: a });

  // prints out "untouched" as should
  console.log(b.options.ref.somevar);

  // Let's change the variable (direct access, bad)
  a.somevar = "changed";

  // b's reference should still point to a, right?
  // In that case the following should print "changed",
  // but because our reference object was copied instead
  // of retaining reference to it, we just get "untouched"
  console.log(b.options.ref.somevar);

I don’t know why MooTools wants to make a copy of arguments in setOptions() – propably for performance reasons.

Catching silent Javascript exceptions with a function decorator

The one utterly annoying thing with the otherwise excellent Firefox/Firebug combo is that some exceptions are let silently through without being end up to be visible in the Firebug console. This makes debugging very difficult, unless you are aware of the phenomenon. I am not sure whether this is caused by some internal Firefox logic flow, since IE + Visual Web Developer doesn’t seem to be affected by this.

Since this problem pops up constantly, I decided to create an easy way to deal with the situation. I decorate all functions which made have silent exceptions (e.g. one called from document load event) with a custom logger function which will first log the exception and then rethrow it.

Thus instead of writing (JQuery example)

myfunction() {
    // crash here
    var i = foobar; // missing variable foobar
}

$(document).ready(myfunction);

write

myfunction() {
    // crash here
    var i = foobar; // missing variable foobar
}

$document.ready(logExceptions(myFunction));

or

// myFunction can be bind to many events and exceptions are logged always
myfunction = logExceptions(function() {
  // crash here
    var i = foobar; // missing variable foobar
});

$document.ready(logExceptions(myFunction));

The Javascript code for the decorator:

/**
 * Enhancd Javascript logging and exception handler.
 *
 * Copyright 2008 Red Innovation Ltd.
 *
 * @author Mikko Ohtamaa
 * @license 3-clause BSD
 *
 */

// Browser specific logging output initialization
// Supports Firefox/Firebug. Other (Opera) can be hooked in here.
if(!console) {
	// Install dummy functions, so that logging does not break the code if Firebug is not present
    var console = {};
    console.log = function(msg) {};
    console.info = function(msg) {};
    console.warn = function(msg) {};
} else {
    // console.log provided by Firefox + Firebug
}

/**
 * Try print human digestable exception stack trace to Firebug console.
 *
 * http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Error
 *
 * @param e: Error
 */
function printStackTrace(e) {

	var msg = e.name + ":" + e.message;

	if (e.fileName) {
		msg += " at " + e.fileName + ":" + e.lineNumber;
	}
	console.log(msg);

	if (e.stack) {
		// Extract Firefox stack information. This tells how you ended up
		// to the exception in the first place. I didn't find
		// instructions how to parse this stuff.
		console.log(e.stack);
	}
}

/**
 * Decorate function so that exceptions falling through are printed always.
 *
 * Returns a decorated function which will be used instead of the normal function.
 * The decorated function has preplaced try ... catch block which will not let
 * through any exceptions silently or without logging. Even though there is an
 * exception it is normally throw upwards in the stack after logging.
 *
 * @param func: Javascript function reference
 */
function logExceptions(func) {

	var orignal = func;

	decorated = function() {
		try {
			orignal.apply(this, arguments);
		} catch(exception) {
			printStackTrace(exception);
			throw exception;
		}
	}

	return decorated;
}

Speeding up Plone loading with PTS_LANGUAGES

If you are not a Finnish speaker (like 99,9% of you) you might not want to (re)load Finnish and other unwanted language catalogs during the Plone start up. This is possible for Plone 3.1, as Reinout van Rees explains (found out afterwards).

For your Plone launcher, set environment variables (space separated list)

PTS_LANGUAGES=en mylanguagecodehere

If your Data.fs is not fresh (i.e. you have an existing Plone instance) there is still one task to do. Go to Placess Translation Service in Zope. Delete all translation catalogs. If there exists a translation catalog entry in ZODB a reload event seem to be triggered even though PTS_LANGUAGES settings is effective. Restart Zope. Maybe this is a bug? Do this on a development box only – this code seems to be quite new. The magic code is in PlacelessTranslationService/load.py.

Facebook requests…

I love you all guys.

I just learnt that Firefox web page screen capture tools (any of them) can’t take web page screenshots higher than short 16-bit interger (32768) pixels. Crash crash crash. But I hope I am alone with my problem.

So, thanks for being so supportive… and it’s not fully rendered (over 250 of them), since after 3200 the image was cut. Excuse me if I am not willing to support your cause.

Facebook requetss