Sunday, October 26, 2008

Extending Object's prototype or making Joose more robust

While working on Joose's unit testing system we created a new test mode that disturbes the environment by doing evil and not so evil things that Joose might encounter in real world situations and then run the test suite.
We discovered that we get some failing tests when Object.prototype gets extended. This is a known bad practice but you'll still find it in the wild. This is now fixed in the latest SVN version of Joose.
We currently test the following scenarios:
  • extending Object.prototype
  • extending Array.prototype
  • extending Function.prototype
  • running with jQuery loaded
  • running with Prototype.js loaded
  • running with Mootools loaded
  • running with Dojo loaded
  • running with YUI loaded
If you have ideas for more things that might be a problem for Joose, please speak up! (Doing thinks like Function.prototype.apply = function () {} is not a valid entry :)

Currently Joose is not compatible with Prototype.js and Mootools. This could be fixed. If anybody really cares about these JS libraries, please scream and we'll fix it. (Of course, patches very welcome. Fix strategy described here)

Update: Joose now runs with Prototype and Mootools. Get the latest SVN if you want to play with it.

Thursday, October 23, 2008

Joose Presentation

Today I held a talk on Joose at today's meeting of the front-end team at work. It talks about the basics of Joose development, facts & figures and walks through some example code.

JS2EE - JavaScript Enterprise Edition

Somebody called Joose the JavaScript Enterprise Edition. I'm not really sure whether that is a good thing or a scary thing :)

Tuesday, October 21, 2008

Test Suite Update

Just wanted to give an update on the progress with our new testing system. First, a big shout out to Jeremy, who converted all remaining tests over to the new system this weekend.

We are currently working out the final kinks, but it looks really good. You can check out the new test runner at this URL. There do seeem to be still issues in Safari though which sometimes go away when hitting reload.

Sunday, October 19, 2008

New Test Suite

We are currently working on moving Joose to a more robust test suite. While Joose's original test suite format was already based on TAP, it was missing many features expected from a test harness, mainly it didn't support being run from the command line.

The new test harness was developed by Jeremy and it gives us the following advantages:
  • Support for command line tools (Rhino, V8, JScript.NET)
  • Good summary reporting for test results
  • When run in the browser all tests run in a single window (faster than one iframe for each test file)
  • Each test gets their own lexical scope, so that variables won't pollute the global namespace
  • Good support for tests that run asynchronously: The test runner now waits until all tests were executed or their was an error
We are still working on moving the test files over to the new format. All test files are located in ./tests/. The old ones have a simple .js extention and the new files use .t.js. If you are thinking about joining Joose development, moving over a test file would probably the perfect way to get your hands dirty. If you are interested, join the mailing list.

Tuesday, October 14, 2008

Non-anonymous anonymous functions

I've been browsing a lot of JavaScript code from various sources today and that made me think it would be nice to talk about a little know property of the JavaScript language that doesn't seem to be widely used:

When doing advanced JS programming, one ends up writing a lot of anonymous functions (often in the form of callbacks like this
ajaxRequest(function ( data ) { ... })

In this example the function passed to the function ajaxRequest does not have a name; hence it is anonymous. The problem with this is that once you go into debugging, stack traces start to become quite unreadable because, well, the stack frames don't have names that make them easily identifiable. Now to the little known feature: You can give a name to any JS function, simply rewrite the code above to
ajaxRequest(function ajaxResponseHandler ( data ) { ... })

and the function will get a name in stack traces. When writing object oriented code it can also be nice to encode the class or namespace name in the function name. One possibility is to abuse the beloved $ character as a name separator:
ajaxRequest(function MyClass$ajaxResponseHandler ( data ) { ... })


When coding for non-public projects one can, of course, choose whether this extra typing is worth the effort, but for library code one should always name all anonymous functions. (and yes, I'm looking at you jQuery (and yes, I know, patches welcome))

By the way: I tried whether it would be possible to actually set the name of a function at runtime (so a meta framework (like Joose :) could add names and namespace info. Unfortunately, the name property is read-only in firefox, so this is not possible. By the way2: That mozilla chose to use the non-standard name property for function names can lead to pretty weird bugs when doing JS programming, because the probability that user code wants to use the name property for its own purposes it actually quite high. __name__ would probably have been wiser.

Saturday, October 11, 2008

blok is a featured project of Google App Engine

blok, the most sophisticated Joose example application, was made an Editor's pick on the application gallery of Google App Engine and is listed as a featured project on the app engine homepage. Thanks for the extra traffic :)

This is the second time this honor was applied to a Joose based project. Lets hope for more.

Wednesday, October 8, 2008

Persistence with Joose, CouchDB, etc.

Joose's super easy to use automatic object JSON serialization and deserialization using Joose.Storage really seems to open up people's imagination.

Mike Walker wrote about integrating Joose with a CouchDB backend in his blog and after I invited hime to join the Joose mailing list we started a very interesting thread about attaching further db backends to the OR-Mapper that was originally created for the Google Gears and HTML5 databases.

Other people are interested in a CouchDB backend for Joose, too, which might lead to very interesting applications. Whether going back to a quasi old-school client-server, where the server is actually a database and not an application server, is of course another story.

blok, the Joose sample application for collaborative web-based editing of diagrams actually uses a programming model where the server plays a rather insignificant role and all logic is implemented on the client.
While blok currently uses a minimalistic Python backend that runs on Google App Engine, it could easily be ported to alternative backends such as CouchDB.

Sunday, October 5, 2008

Exceptions in JavaScript

I did some intensive research into the topic of JavaScript exceptions yesterday. My main concern was, that while it is possible to throw basically every kind of object (Strings, numbers, booleans, Objects) via the throw operator, only the JavaScript standard exceptions will show up with a stack trace in firebug and only those will be clickable to jump to the source which caused the exception.

My research showed that it is indeed not possible to get firebug to show stack traces for custom exceptions. The main reason being really simple: The firebug console is a reflection of the standard error console and thus it cannot show more than is being shown by the standard error console.
There does not seem to be an easy way around it from the firebug point of view. I still hope that firefox will eventually add core support to enable a better experience in the firebug error console, but wel'll have to wait for that.

Among the things that I tried where to copy a core-JS error and manipulate the stack trace, etc. But all of those things won't trick the browser into thinking it has a real core exception.

Here are some basic advises when dealing with exceptions in JS
  • Never throw an exception in an asynchronous callback!!! Nobody will be able to catch it (without maybe playing ungly games with a global exception handler in window.onerror).
  • Use onError callback arguments instead.
  • I would not recommend to use custom exception classes in JS right now (but I would be very interested in a good best practive article on this topic, and I will do more research in this area)
I have an idea on how to use the built-in Error class as a genereal purpose container for more specialized exceptions. Update: This is not possible, either, because Error stringifies it's message parameter during initialization, instead of doing it as late as possible :(

Saturday, October 4, 2008

Type Constraints and Type Coercions

Jeremy and me continue to work on the type contraint and type coercion system for Joose.
Just a quick heads up to what this actually means using an example from the test suite (please be aware that the naming of types will likely change until the next release)
Class("CoercionTest", {
has: {
numAttr: {
isa: TYPE.Num,
coerce: true,
is: "rw"
},
strAttr: {
isa: TYPE.Str,
coerce: true,
is: "rw"
}
}
})
The class above has two attributes numAttr and strAttr. These are constraint to be of TYPE.Num and TYPE.Str. That means that it will not be possible to set these attributes to anything that does not match those types. However, the coerce: true property activates coercion which in turn activates magic that can convert a value from one type to another.

Some examples from the case above
  • coerce.setNumAttr("2") will assign the number 2 to the attribute numAttr (not the string "2")
  • coerce.setStrAttr(2) will assign the string "2" to the attribute strAttr
  • coerce.setStrAttr(["a", "b"]) will assign the string ["a", "b"].toString() to the attribute strAttr.
Type constraints will help to make your code
  • more correct (because values are contrained to the correct type)
  • more correct (because we already tested the type checks in Joose's test suite)
  • more declarative
  • shorter (because of centralized coercions)
  • more correct (because we already tests the type coercions in Joose's test suite)
The next steps are to provide a standard type system for Joose with all general coercions in place. This will make working with JavaScript in the browser a lot more fun, because
  • you get a validation framework for free
  • all data coming from the user (like input fields, etc.) is text based and coercions turn these into meaningful data automatically.
The type system is actually in place already, but most of the coercions are still missing. Since most coercions turn strings into structured data, many coercions must actually be localized (think "13,000.45" va. "13.000,45"). Thus, we will also provide hooks to activate coercions based on the current locale. Joose will ship with coercions for english speaking countries and I'll write extentions for Germany.

We'll keep you posted with updates about the type system.