Wednesday, December 31, 2008

Multicast feature added to UniversalComet / Chat sample app

One of the goals of my project UniversalComet is to enable client-only P2P applications. I thus added the feature to subscribe to scopes and do multicast posts to all subscribers. This enables "discovering" peers and talking to all of them at once.

The feature could be especially useful for things like widgets or facebook apps.

Using this feature I created a sample chat application.

The chat example is hosted on the Google Code SVN repository. There is no server side magic involved. The whole chat is implemented in a couple lines of JavaScript code (using jQuery for DOM access):

$(document).ready(function () {

// Output a message
var log$ = $("#log");
function log(msg) {
log$.text(""+msg + "\n" + log$.text())
}

// Make me a server with Google Gears support enabled
var server = new Addressable.Server({ useGears: true });

// When a message arrives, just "log" it
server.onmessage = function (message) {
log(message)
}

// Out subscription scope is the current URL
var scope = location.href;

// Connect to the UniversalComet server
server.connect(function (id, url) {
log("Connected.")
// When connected subcribe to the scope
server.subscribe(scope, function () {
log("Joined channnel")
// When subscribed, post "Hi All"
server.post(scope, "Hi All")
})

// Subscription expire after 5 Minutes. Renew ours every 4 Minutes.
setInterval(function () { // renew subscription
server.subscribe(scope, function () {})
}, 1000 * 4 * 60)
})

// When the "chatForm" is submitted post the message to the scope on UniversalComet
var message = $("#message").focus();
$("#chatForm").submit(function (e) {
server.post(scope, message.val())
message.val("")
e.preventDefault() // Dont really submit the form
})

})

Security
Anyone can subscribe and post to any scope. You can work around this by using "secret" scope names and doing the subscription and posts on your server to work around this. I might add Authentication to the process later. However, UniversalComet is meant as a low-level API for doing Comet. There is nothing stopping you to layer any authentication layer on top of it that you like.

Compatibility
UniversalComet has now been tested on the following platforms
  • FF3 on Mac (With and without Google Gears)
  • FF2 on Windows (With and without Google Gears)
  • Safari 3 on Mac
  • IE7
  • iPhone
  • Android

Monday, December 29, 2008

UniversalComet - Making every client addressable through URIs

Based on my earlier experiments, I have developed a JavaScript library that makes it extremely easy to incorporate "comet" or server-push technology into any web application without need for special programming or any special support on the server. Ressources needed on the server are also practically zero.

When you use the JavaScript library, you will receive an URI that identifies the client. Now you can make simple HTTP-GET requests to that URI with a message parameter and the client will receive the message immediately. Because only your application will know the un-guessable URI, the client should be save from unwanted messages. The use of HTTP-GET messages also allows sending messages in a "P2P"-fashion from client to client using JSONP cross-domain-messages.

To use the JavaScript library put this piece of code on your website:
<script type="text/javascript" src="http://universal-comet.appspot.com/static/client-server-mini.js"></script>
<script type="text/javascript">
var server = new Addressable.Server();

server.onmessage = function (message) {
alert(message)
}

server.connect(function (id, url) {
// send url to you server using AJAX
})
</script>
A fully working HTML-page can be copied from here.

The function that is passed to the connect-method receives the URI of the client and as soon as messages arrive they will be send to the onmessage-callback.

A Google App Engine application is used as a kind of reverse-proxy for the messages to the clients. Thus there will be no extra load on your server. The JavaScript application always maintains only one connection to the comet-proxy per domain. If a clients has Google Gears installed (Google Gears is not needed for operation) there will only be one connection per web browser. This minimizes the load on the comet-proxy.

The JavaScript application uses "channels" to differentiate between different windows that the same client has open at any given time. These are cached in window.name. If you set window.name yourself this value is used. You can also set server.setChannel("myChannel") before you connect to name the channel yourself.

You can try out the library in the iframe below. This is extremely alpha, practially untested code. If you have a problem, please post a comment (Rudimentary testing has been done in FF3 and Safari on the Mac, FF2 and IE7 on Windows. All with and without Gears.).


Update: There is now a chat sample app.

Thursday, December 25, 2008

Bridge between Ext and Joose

Nickolay Platonov of Symbie has developed an extremely interesting bridge between Joose and Ext. The cool thing is that he has overriden Ext.extend to bootstrap all Ext classes to be full blown Joose classes. Meaning you can easily inherit from them using Joose facilities and especially apply roles to ext classes and object.

More info can be found in this post to the Ext forum and check out the joosified Ext samples.

Nickolay's approach can, of course, be applied to any JS framework that provides a pseudo-class layer so I'm looking forward to joosified YUI, Prototype, etc.

Merry Christmas! Long live the Joosification.

Monday, December 8, 2008

The first days in the clouds

Thanks to Ajaxian and many others there was a lot of traffic on my post about the JavaScript-in-the-cloud-system.
The first effect was that the mighty cloud went down all the time. This was largely due to the fact, that the system requires a somewhat long running (100-600 milliseconds) process on the App Engine servers. Google placed very strict quotas on these requests in order to keep their system stable und thus they frequently disabled the application. Marzia suggested on the App Engine group to ask for an increased quota and it looks like Google followed suit. At least the problems seems to have disappeared.

Since this was all just an experiment, I don't really know whether I'll do anything with it. It really seemed to drive people's imaginations, though. Some of this ideas where:
  • Create SETI for JavaScript
  • Start a botnet
  • Calculate PI
  • Use it to build a very parallel (as in every user of the internet) web crawler
  • Build this into Flash banners to put them to good use
In any case the system shows that Joose can really increase JavaScript's productivity. The whole system was created between 01:30 am and 05:30 am which I think is not too much time for something which could also have just not worked.

If anybody is interested in using the system, just drop me a mail malte.ubl (at) gmail.com or write to the Joose mailing list.

Saturday, December 6, 2008

Massively parallel crowd-sourced JavaScript app server cloud

Reporting live from the "Why? Because you can!"-department:
Probably due to the fact that I watched way too many episodes of Terminator - The Sarah Connor Chronicles, seeing people talk about Skynet, or because I really wanted to build Google App Engine applications with JavaScript or because I have way too much time on my hand, I decided to build a JavaScript application server that runs within the browsers of the people that visit the site that the app server is delivering. Are you following me? :)

The system works as follows:
  • When a user makes a request to the site
  • ...the request is handled by a Google App Engine application
  • ...that puts the request into a request queue
  • Meanwhile on another computer that runs the JavaScript app server within a Google Gears worker within the browser
  • ...a comet-client maintains a pseudo permanent connection to the App Engine app
  • ...looks into the request queue and starts to process the request
  • ...when it is finished it sends the response to the App Engine app
  • ...which immediately send the request back to the client that originated the request in the first place.
Crowd-sourced cloud computing
  • Ressouce requirements on the server side are reduced because every client can share some of its own ressources with every other user of the system
  • Works with my favorite language JavaScript
  • Enables absolutely seamless integration of client- and server software
Limitations
  • Every app server is totally untrusted.
  • For security reasons the response of the JavaScript server application must be JSON. It cannot be plain HTML, because every untrusted client could inject evil scripts into the stream
  • Google App Engine unfortunately does provide a good way to implemented comet-style applications with long-polling because they enforce very strict rules with respect to request timeouts
  • The App Engine SDK builtin-web server is not multi-threaded. Thus the application can not be tested (easily) within the SDK but has to be deployd to the production system.
  • My implementation is very-very proof-of-concept do-the-easiest-thing-that-could-work style with no error checking and various evil race conditions with respect to the request queue.
  • There is currently no builtin way to persist data. However, applications may of course use any kind of web-service that is accessible via JavaScript.
  • There is currently no way to read-or-write HTTP headers from the applications
Demo Client
You can try the the demo application (a simple counter here). It will only work if you either started the server yourself (below) or if somebody else is currently running the server application.


Demo Server
The server is running in this iframe:


The app engine application might be disabled due to overuse of quotas. If that is the case, I'm sorry.

If you are interested in come code, check out the implementation of the server.

Sunday, November 30, 2008

JavaScript packaging

With the current generation of browsers page load time is highly depended on the number of JS files loaded. Thus it makes sense to minimize the number of http-requests by combining multiple JS files in combined packages. This makes even more sense because the effectiveness of gzip-compression increases on larger JS files as opposed to the same source distributed over multiple files.

Most advanced JS projects will have some kind of mechanism within there build process to statically determine which JS files are needed for a particular page or application and assemble these together (JavaScript minification with a tool like the yui-compressor would also we applied at this point).

Here are some common simple strategies to make those JS packages:
  1. Traverse the JS directory recursively and put all files into the package
  2. Mantain a list of JS files per page/site/app and use that to assemple the JS packages
  3. Include support in the templating system to arrange for the generation of an appropriate JS package
We are currently using a modified version of strategy 2 at work. Every page loads a "meta" JS file that mostly defines an array of needed JS files. During development this file actually generates script tags via document.write to load the required files. This makes sense because during debugging you want to have errors and break points per file. Once we deploy the application for testing, a program analyzes those "meta" JS files to compile packages that are then loaded instead of the meta files.

In a recent post to the Joose mailing list, we talked about different strategies to find the ideal packages to minimize load time. My current thinking is that it is very hard to do much better than to load everything (for the whole app / sub-site) at once.

Here are some examples for strategies to determine what to put inside a JS package:

Page A needs JS file 1,2,3,4,5
Page B needs JS file 2,3,4,5,6

In order to minimize http requests, the strategies would be to

Strategy X:
1. Visit page A , load a package containing all needed JS files
2. Visit page B, once again load a package containing all needed JS files
  • plus: Simple
  • minus: Loading too much data
Strategy Y
1. Visit page A, load a package containing all needed JS files
2. Visit page B, somehow determine that we were already in Page A and use that package plus and extra request for file 6
  • plus: Minimal data
  • minus: Very complex, needs support on the server for dynamically assembling JS packages.
Strategy Z:
1. Visit page A Load a package containing all needed JS files for the entire App
  • plus: Simple
  • plus: Maximum result from zip-compression
  • minus: User loads code which he might not need eventually
My current thinking is, that if (and only if) the package resulting from strategy Z is not "too large" it is the best strategy most of the time.

If it is possible to easily determine disjunct packages of JS files, it makes of course sense to load these separately. In this case, it is, however, highly likely that we are talking about separate applications anyway.

Tuesday, November 25, 2008

JooseX: Joose extensions

First of all I want to say thanks for the kind words about Joose from the guys that attended my session at the hamburg barcamp.
I'm currently doing a lot of Joose programming at workt. It is kind of unfortunate that it won't be anything to show off from a JS perspective because the code is embedded into some serious worst-case legacy code. Anyway, Joose proves to be a very stable environment to build on and my personal focus will now shift toward extending Joose on the edges without bloating the core.
Those new extensions will live in the JooseX namespace and will be loosely coupled to the core so that they can be used on a case by case basis. Currently under development are the following modules:
  • Multiple roles for easy dumping of objects during debugging
  • A logging framework
  • A role for implementing the Singleton pattern.
  • A databinding framework that binds Joose objects to DOM elements (this is already in SVN called JooseX.DOMBinding.JQuery)
  • An MVC framework for event-driven client-sided programming (Although this is the most interesting part, it might not be released in its current form, because I'm still very much experimenting on this end)

Sunday, November 23, 2008

Joose presentation at barcamp hamburg #bchh08

I went to the Hamburg barcamp today. Overall the conference was great and most speakers really knew what they were talking about. My favorite session was done by a real bottom-dwelling SEO guy. Quite funny. Many thanks to Otto for providing the venue and free food and drinks.

I did a session about software development with JavaScript and Joose (based on the same presentation that I prepared for work 4 weeks ago. It was very well received and maybe Joose scored a couple more users.

Here are the slides that I showed today (I only changed the date):

Sunday, November 16, 2008

Joose 1.1 released

We are proud to announce the release of the newest version of Joose, the meta-object system for JavaScript.

You can download it on the Joose download page.

Version 1.1's main focus went into improving compatibility of Joose with other JS libraries and with user code that was not designed to run with Joose. During this release we also moved Joose's unit test suite to Jeremy's awesome new TAP based testing library.
Joose is now regularly tested to run together with these JS libraries:
  • jQuery
  • YUI
  • Prototype.js
  • MooTools
  • Dojo
Other changes are:
  • Joose is now compatible with the Rhino JavaScript engine. See this post for instructions.
  • Extending Object.prototype no longer breaks Joose (You should still not do it :)
  • Method modifiers in Roles are correctly applied to classes.
  • Roles can now define meta roles that are applied to the meta class of a class that is using the role.
  • The minified version of Joose is now compressed using the YUI compressor which saves 16 KB on the file. (Joose's file size is now 40 KB, 12 KB when GZipped)
  • Various bug fixes
We are still very actively working on the Joose type system that will be released with the next major release of Joose.

About Joose:

Joose is a self-hosting meta object system for JavaScript with support for classes, inheritance, mixins, traits, method modifiers and more.

Joose makes object-oriented programming with JavaScript easy, declarative and very productive. The Joose meta-object system is multi-paradigm. It supports class-based and prototype-based programming styles as well as class-based inheritance and role-based extention.

The Joose framework has been successfully used in multiple production systems for seven months now and has been proven to be very stable. Joose is being tested using an automated unit-test suite that is being run in all major browsers (Firefox, IE, Safari, Opera and Chrome).

Saturday, November 15, 2008

Joose now passes all tests under Rhino

Joose has been running alright under Rhino, but there have always been some failing tests due to different behavior in Rhino when compared to most other JavaScript engines.

Most JS engines traverse objects in declaration order. That means when you loop over an JS object like
{
isa: "SuperClass",
does: "Role",
methods: {
test: function () {}
}
}

the loop will return the properties in the object in the order "isa", "does", "methods".

Now because object literals are used to initialize Joose classes this traversion order can be really important when Joose is initializing classes. While all JS engines used in web browsers use the de-facto-standard traversion order, Rhino traverses objects in random order. It is important to state that the ECMAscript standard does specifically not define the traversion order, so from a standards point of view Rhino is right on this one.

While we might add automatic detection of Rhino to Joose, for now you will have to define this.CHAOTIC_TRAVERSION_ORDER = true in global scope before loading Joose to enable the work-around.

This work-around works like this. No matter how you write your class declarations, Joose will always evaluate the class properties "isa", "does", "has", "method", "methods" first (and in that order).

To try out Joose under Rhino check out Joose from svn and run playground/rhino/rhino_test.js with Rhino.

Monday, November 10, 2008

Offtopic: Looking for Nuclear engineers with JavaScript background

Please excuse this Spam in my own blog. My employer sinnerschrader is doing really well, we have lots of money to make it through the crisis and we are looking for:
  • Nuclear engineers with JavaScript background
  • Mossad Agents with Java affinity
  • Bored SAP slaves
  • and all other excellent Software-Engineers!
More info here or in this spot:

Monday, November 3, 2008

Joose test trial

We are preparing a new Joose release and we'd like to get feedback on test results under different configurations. If you have tests failures (or you don't) please post them here or at the mailing list: joose-js@googlegroups.com

As described in a earlier post, we can now run the Joose test suite under different real world scenarios. Because JavaScript is not very strong when it comes to separating code that is run within the same process there can always be side effects when code does weird stuff. We try to make Joose as robust as possible against these side effects.

The current known issues are
  • Google Chrome: Test file #7 crashes after 39 tests
  • All browsers: When run with Prototype.js two test in the jsonpickle test file fail
Here are the links to the different versions of the test suite:
Please report all failures. I personally tested with FF 3.0.3 on Mac, IE7, Safari 3 and Chrome.

Sunday, November 2, 2008

Turning all JSON web services into JSONP web services

I created a very simple Google App Engine application on Friday that helps you when somebody built a JSON based web service but did not mind to make it JSONP compatible (JSONP is a standard to do cross domain AJAX requests and it is supported by all major JavaScript libraries).

To use it simply call:
http://jsonpgateway.appspot.com/?url=YOUR_URL
or:
http://jsonpgateway.appspot.com/?url=YOUR_URL&callback=YOUR_CALLBACK
to us a customized callback parameters.

Here are some working examples:
Currently only GET requests are supported, so fully restful services are off limits. However, I guess, one could put in some more code to support different request methods.

To ensure that the payload is really JSON it is parsed and reencoded on the server.

I'm not really sure whether this service is secure enough. If somebody makes a point that it should be taken down then I will.

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.

Monday, September 29, 2008

Eval vs. Closure

Yesterday I made some experiments with respect to the relative speed of using closures vs. eval. For Joose these are the two options when creating accessor methods for attributes.
The results are quite interesting
  • On average executing a function that is not a closure and was created using eval is 30% faster than executing a closure
  • However, creating a function using eval takes about 200 times longer on worst case (FF3 on OSX)
This means using eval would create some significant gains for if you are executing an accessor method many times (you will need to be in the 10th of thousands for it to make a noticable difference). However, the increased cost for actually creating the function is currently prohibitive. With Joose we make sure that the compile time remains very small, because it will directly affect your page load time.

Thus, this will not go into Joose by default. We might still, however, create an option that lets you enable compiling accessors with eval for single attributes which are used very heavily.

Saturday, September 27, 2008

The == Operator in JavaScript

While working on the type constraint system, we got bitten by a pretty unexpected behavior of the == operator in JavaScript, that I wasn't aware of before. In our case is made a test case related to coercion pass, although no coercion was actually applied.
Here are some examples from the firebug console, that show the behavior:
>>> 1 == true
true
>>> 0 == false
true
So 1 equals true and 0 equals false. This can actually come in quite handy in many situations, where you are working with languages that have a similar understanding of truthness on the server side. Using the === obviously helps in this situation.

Friday, September 26, 2008

Type Constraints in Joose

Jeremy Wall of Google provided a great patch to Joose to actually hook up the long standing implementation of type constraints and coercions into the default attribute meta class.

So what does this actually mean:

First: You can build Types which are basically just things that express certain contraints for a value containers like an instance variable.
This is a type that will only allow boolean values:
Type('BooleanTest', {
where: function(value) {
if (typeof value == 'boolean') {
return true;
}
return false;
}
})
Now where this gets useful is if you add what is called coercions, which are just little functions that look at data and tranform them in a way that they match a type. Here is the type declaration with a coercion added, that turns 0 into false and other integers into true:
Type('BooleanTest', {
where: function(value) {
if (typeof value == 'boolean') {
return true;
}
return false;
},
coerce: [{
from: TYPE.Integer,
via: function (value) {
if ( value == 0 )
return false;
return true;
}
}]
}
);
Now we can build a class that constraints it's instance variables to be of type BooleanTest like this:
Class("BooleanTypeConstrained", {
has: {
attr1: {
is: 'rw',
isa: TYPE.BooleanTest,
coerce: true
}
}
})
We have to add the extra coerce: true, in order to enable the coercion because it does have a certain impact on runtime performance. What we can do now is this:
var constrained = new BooleanTypeConstrained();
constrained.setAttr1(1)
Without the coercion this would fail, because the field attr1 is contrained to be a boolean. However, because we added a coercion that transforms integers into booleana, this still works (and it actually sets the value of the instance variable to true).

I think that this can be a big thing for JavaScript programing, because when we do client side programming, dealing with user input is very important. With type coercions this becomes very declarative and easy. For example, you can have the user input a date in many different formats and then have coercions that transform these strings into instances of Date.

Thursday, September 25, 2008

Version 1.0 of Joose released



We are proud to announce the release of Joose 1.0. Download it now.

What's new in this version?

Joose is a self-hosting meta object system for JavaScript with support for classes, inheritance, mixins, traits, method modifiers and more.

Joose makes object-oriented programming with JavaScript easy, declarative and very productive. The Joose meta-object system is multi-paradigm. It supports class-based and prototype-based programming styles as well as class-based inheritance and role-based extention.

The Joose framework has been successfully used in multiple production systems for five months now and has been proven to be very stable. Joose is being tested using an automated unit-test suite that is being run in all major browsers (Firefox, IE, Safari, Opera and Chrome).

Tuesday, September 23, 2008

All new Version of blok

Over the last couple days I developed a major update for blok.
blok is a web based tool for colaborative editing of simple diagrams and user interface prototypes. Try it out here and please vote for blok at the app gallery.

Among the improvements are:
  • Ability to save and load documents with your Google account
  • New Welcome-Screen
  • Support for templates
  • Support for custom shapes (not yet enabled by default)
  • Better support for undoing operations that were performed on groups of shapes
  • More correct syncing between multiple editors
  • Faster speed in many situations
  • Better support for IE7, Safari and Chrome
If you find an error, please file a bug report.

Thursday, September 18, 2008

Truly private instance variables in JavaScript

Standard javascript objects do not support truly private instance properties (at least in a cross platform fashion). This means that even if you create get- and set-methods for your properties, an evil abuser of your interface can always get around this by simply peaking inside the object.

Leaving the arguments aside whether this is actually a problem or not, one can achieve the affect of private instance properties that only grant access through accessor methods by using closures which refer to a storage variable. A downside of this technique is the increased memory usage and increased object construction time, because these closures will have to be created upon every object construction so that the new object refer to their own private storage variable.

Here is some code that is demonstrating this technique:
MyClass = function () {
makePrivate(this, "test")
};

function makePrivate(object, name) {
var storage;

var field = name;

object[field] = function (newVal) {
if(arguments.length > 0) {
storage = newVal
}
return storage
}
}


var o1 = new MyClass();
var o2 = new MyClass();

o1.test(1)
o2.test(2)

alert(""+ o1.test() + o2.test())

o1.test(3);

alert(""+o1.test() + o2.test())


Another downside to this technique is that your instance vars are so private, even firebug cannot see them, so debugging will be much harder.

I'm currently pondering whether this technique would be a nice addition to Joose (hidden behind the regular class construction syntax). Putting this inside an attribute meta class would at least allow to enable a kind of debug mode that would make the vars visible during development.

While privacy might not be so relevant when you build all code for yourself, it might still be useful when you build a public JS API like Google Maps. True information hiding makes the interface much more explicit and enables you to change the internal representation of your objects later on without having to take care of people who relied it.

Monday, September 15, 2008

All Tests pass with JScript .NET

As of the last commit all Joose tests pass under JScript .NET.

What is not so nice is that JScript .NET wants to report an error to Microsoft every time you deference a non-existant property as a function. Oh, well.

Another interesting thing is that JScript .NET actually passes more tests than JScript. There is one unofficial feature in Joose that allows un-applying of roles which contain only method modifiers (yes, a plugin system on steroids!) at runtime. I haven't found a way to make this work under JScript, because it can only (easily) made to work with the __proto__ property which enables exchanging the prototype of a single object at runtime. Well, under JScript .NET there is no __proto__ property, but it still works. There must be something else going on in the background. Joose is also switching object.contructor to a new value and maybe .NET is using that path to find the object's prototype property?

Sunday, September 14, 2008

Joose now works with JScript .NET

I'll start a new job soon that will involve development with .NET so I figured it might be interesting to get Joose to work with JScript .NET.

Turns out, it works! Changes to Joose itself were minimal:
  • The .NET compiler actually spotted possible errors in Joose, which were easily corrected
  • While overriding toString seems to be possible, the JSC compiler complains about it when you do it too obvious :)
There was one more hurdle that was a little harder to take, but which might be also useful for other projects that get ported to JScript .NET:
Although there is a global object in JScript .NET, it doesn't have a name so you can't easily set new properties on it. Joose, however, wants to create new global objects when you make a module or class, so it needs this functionality. Turns out, it is quite easy to make it available:
When you execute a function declared in global scope, the 'this' variable refers to the global object, so you can assign that to a variable to make it available to the outside world. Here is a example that is using the name window for the global object (just like it is called in the browser):
var window;

(function() {
window = this;
})()
You are invited to try it out. You need to checkout Joose from SVN and then go to the directory playground/jscript.net/. The file test.bat will execute all the test files from the testsuite. You will need to have jsc (the JScript .NET compiler in your path) which is part of the .NET framework in your path.

There will be some crashes during the test run. These are all related to the JSON library which is used inside Joose.Storage. All other tests run though, so Joose should be very usable.

Wednesday, September 10, 2008

Joose "blutige Kante"

The test suite of Joose svn latest is now available at: http://joose-js.googlecode.com/svn/trunk/tests/test.html

Results welcome!

Refactoring Joose

One of the main features of the next Joose release will be the ability to make extending the class and role building syntax very easy.

Consider this example:
Class("MyClass", {
methods: {
...
},

primaryKey: "id"
})


primaryKey is not a regular property of the class builder. However, the class initializer will attempt to call the method handlePropprimaryKey on the meta class which can then do whatever it wants with the property.

This enables very declarative and special-case class construction styles.

While this has been in Joose for a couple of weeks, up until now there have been special cases for the "standard" class construction properties like "methods" and "has". As of this commit these special cases where completely eliminated.

Turning asyncronous interfaces into pseudo-synchronous interfaces...

... or making some callback-intensive JavaScript look less like bad LISP.

JooseX.DelayedExecution implements a type of mock object that implements the complete interface of the class object given to its constructor.
Every method call will schedule the method call with all its arguments for later execution on the original object.

This enables building asynchronous APIs that look like synchronous APIs.

Example:

This asynchronous code:
myFunc("foo", function (para) {
para.anotherFunc(function (para) {
para.yetAnotherFunc("bar")
})
})
can be turned into:
myFunc("foo").anotherFunc().yetAnotherFunc("bar")
by calling:
myFunc = function (para, callback) {
var result;
var process = function (result) {
delayed.__performOn(result)
}
... do something in an async callback that sets the variable result
return new JooseX.DelayedExecution(typeOfResult) // typeOfResult is the Joose class of the result object
}
I personally think that the latter is much more readable in certain circumstances. However, an unfortunate maintainer of the code might not know that the code is only hiding asynchronous execution which can lead to some hard to find bugs, because code is executed in random or at least async order.

For a use case of this technique, see the last post.

While this is probably so dangerous, that it should never be used, it was still fun to develop it.

Saturday, September 6, 2008

jQuery style result sets for OR-Mapper

I implemented a couple shortcuts that enable working with datasets in a jQuery style.

As an example, the sticky note code had a couple lines that looked like this:

Note.selectAll(function (notes) {
notes.each(function (note) {
note.redraw()
note.show()
})
})


The API is inherently asynchronous because that is the only way that is provided by the HTML5 database API.

This can now be written as:
Note.selectAll().draw().redraw().show()


This is pretty dark JavaScript magic going on, because all methods after selectAll won't really be executed until the select has actually been executed.
I like this API style much better, but it has some serious draw backs:
  • In the Gears version you loose the transaction context because evil global vars are involved (in my mock up implementation of the HTML5 api)
  • If there is something coming in the next line, one would expect it to be executed after show() which is not the case.

Tuesday, September 2, 2008

Joose is a featured project on Google Code

Joose was selected as a featured project on the Gears API page.
There is now a landing page on Joose's Google Code site that summarizes all the tools included in Joose that help with working with Gears.

Joose now has a logo

Sunday, August 31, 2008

Sticky Notes example rewritten

The initial version of the sticky notes example was pretty much an exact copy of the non-Joose version, which sucked, because the code was really hard to understand and didn't work too well outside of the Safari Browser.
I rewrote it using jQuery and on the way implemented a generic databinding system to attach Joose objects to jQuery objects and vice-versa. The new code is way shorter and should pretty much speak for itself (understanding what really happens is a totally different matter).
If you are interested in the jQuery databinding, take a look at the code, but beware that it dwelves deep into the meta magic of Joose and isn't ment for the lighthearted or people who like extensive documentation :)

Friday, August 29, 2008

New OR-Mapper Example: Sticky Notes

I created a new example that uses the new OR-Mapper for the HTML5 and Google Gears database.
It is based on the an example from the WebKit guys and it is currently ported one-to-one. Thus it works best in WebKit browsers like Safari and only mostly works in Firefox 3. I didn't test any other browsers yet.
If it works you should be able to place notes on the screen which will persist across page reloads.

Wednesday, August 27, 2008

More work on the OR-Mapper

just some updates that make the tool actually useful:
  • There is now a remove method in every entity to delete it from the database
  • Transaction support for Gears. Transactions are queued, so you can safely nest them in callbacks but they wont be executed until the current transaction is done (same behavior as with HTML5 databases)
  • A little meta class magic to make Entity definitions even nicer:
This is how entity definitions look now:
           Class("Person", {
isa: ORM.Entity,

tableName: "person",

hasOne: {
mother: {
isa: function () { return m.Person }
}
},

hasMany: {
cars: {
isa: function () { return m.Car },
foreignKey: "owner"
}
}
});

If you are interested in how these DSL like class definitions are
achieved using the Joose framework, this commit might be interesting:

Monday, August 25, 2008

OR-Mapper for the HTML5 database and the Google Gears database

Last week a guy on the Joose mailing list asked whether the example object relational mapper included with Joose could be used to build iPhone web application using the webkit implementation of the HTML5 database API. The immediate answer was that it wasn't possible because the OR mapper was designed to work with the Google Gears database which is currently not compantible with HTML5.

So I did two thinks
  • I implemented a wrapper for the Gears API that makes it look like the HTML5 database API (There was already one linked from Ajaxian but all the download links were dead)
  • I ported the existing OR mapper to use the new API
This means that the OR mapper can be used with the Gears db and the HTML5 db without any changes.

The HTML5 database API in inherently asynchronous. The reason being that databases requests should not block script execution and thus decrease the responsiveness of the GUI.
I, personally, don't like the API because thinks start to look a lot like degenerated LISP once you get down to the 16th callback level, but, I guess, performance was more important than beauty for the API designers.

The primary change with respect to the synchronous Gears version is that now all operations that talk to the database like Entity.save() or Entity.newFromId() take an extra parameter that is a callback function which gets executed as soon as the db operation is completed.

Here are some examples from the test suite of the OR-Mapper.

Declaring an entity looks like this (A Person that has a mother and many cars):
    Class("Person", {
isa: ORM.Entity,

classMethods: {
tableName: function () {
return "person"
}
},

has: {
mother: {
metaclass: ORM.HasOne,
isa: function () { return m.Person }
},

cars: {
metaclass: ORM.HasMany,
isa: function () { return m.Car },
foreignKey: "owner"
}
}
});
And using the classes looks like this (I warned you about the LISP effect):

/*
ok, isEq, canOk, etc. are functions from the unit testing framework that I use
*/

ORM.transaction(function (tx) {

var mother = new MyEntities.Person();

mother.setName("elke");
mother.setCity("Elmshorn");
ok(mother.isNewEntity, "... mother is a new entity object")

function testPerson (person) {
canOk(person, "getRowid")
canOk(person, "getName", "... there is a name method")
isEq(person.getName(), "malte", "... name is correct")
isEq(person.getCity(), "Hamburg", "... city is correct")
person.getMother(function (mother) {
ok(mother, "... can fetch mother")
isEq(mother.getName(), "elke", "... mother name is correct")
isEq(mother.getCity(), "Elmshorn", "... mother city is correct")
})


ok(person.getCars, "... there is a cars method")
person.getCars(function (cars) {
for(var i = 0; i < 10; i++) {
canOk(cars[i], "getBrand")
isEq(cars[i].getBrand(), "bmw", "... brand is correct");
isEq(cars[i].getModel(), "3."+i, "... model is correct");
canOk(cars[i], "getOwner")
cars[i].getOwner(function (owner) {isEq(owner.getName(), "malte", "... owner name is correct")})
}
var count = cars.length
ok(count == 10, "... there are only 10 cars: "+count)
});
}

mother.save(function () {
ok(!mother.isNewEntity, "... mother is now saved")

var person = new MyEntities.Person();

person.setName("malte");
person.setCity("Hamburg");
person.setMother(mother)
person.save(function () {

var i = 0;
function makeCar() {
var car = new MyEntities.Car();
car.setModel("3."+i);
car.setBrand("bmw");
car.setOwner(person);
car.save(function () {
if(++i < 10) {
makeCar()
} else {
testPerson(person)
MyEntities.Person.newFromId(person.getRowid(), function (aPerson) {
testPerson(aPerson)
endTests()
})

}
})
}

makeCar()
})})})

If you have either Google Gears installed or are using a web browser that implements the HTML5 database like Safari (and other browsers based on webkit), you can run the testsuite yourself.

For more info, check out the source:
The code is currently extremely alpha and missing features. If people show interest I'll push it to production quality.

Saturday, August 16, 2008

Profiling Joose bootstrap time

Joose is self-hosting which means two things:
  1. Most parts of the Joose framework are written using Joose itself
  2. Those parts of the framework where this is not possible (the most fundamental parts) are later bootstrapped to look like the had been written using Joose
The nice thing about this is that all objects within the Joose object system are introspectable using Joose's own methods. It is in a sense pure.
However, bootstrapping incurs overhead (because you do stuff) and I was wondering how big the overhead is. Well, it turns out it is rather small.

I used firebug for profiling, so all my numbers are from Firefox. My computer is a Macbook Pro with 2.5 GHz Core 2 Duo.

Under Firefox 3 compiling Joose takes 17 milliseconds and under Firefox 2 the compilation takes 23 milliseconds, so we are around 2 hundreds of a seconds. Real speed junkies might be worried about this, but tricks like compiling all JS files into one large file probably make a much larger difference.

My conclusion is that Joose's overhead is pretty much negligible, but obviously you have to judge yourself. If anybody is really worried about the 20 milliseconds (maybe because it turns out to be 6000 milliseconds under IE6 :) there is a possible optimization to reduce the bootstrap time to 0, but I won't do it until it is absolutely neccessary.

Thursday, August 14, 2008

Joose now supports jsonpickle

Joose now supports jsonpickle. (At least if you check out the latest SVN).
This gives all the Python programmers the chance to transfer dumps of their Python objects via http to the browser and then instantiate those objects using JavaScript and do method calls on them.

Here is a code example stolen from the jsonpickle homepage:
>>> import jsonpickle
>>> from jsonpickle.tests.classes import Thing

# Create an object.
>>> obj = Thing('A String')
>>> print obj.name
A String

# Use jsonpickle to transform the object into a JSON string.
>>> pickled = jsonpickle.dumps(obj)
>>> print pickled
{"child": null, "classname__": "Thing", "name": "A String", "classmodule__": "jsonpickle.tests.classes"}


And here is how you would use the pickled Python object with Joose:
Module("jsonpickle.tests.classes", function () {
Class("Thing", {
does: Joose.Storage.jsonpickle,
has: {
child: {
is: "rw"
},
name: {
is: "rw"
}
}
})
})

var thing = JSON.parse('{"child": "Robert", "classname__": "Thing", "name": "A String", "classmodule__": "jsonpickle.tests.classes"}');


Of course you may add many more methods to your Joose classes and use them like real objects.

With a simple JSON.stringify(thing) you can send the data back to Python. (You need to call Joose.Storage.Unpacker.jsonpickle.patchJSON(); to be able to use JSON.stringify directly)

Wednesday, August 13, 2008

Automatic Serialization and Deserialization of JavaScript-Objects to JSON with Joose.Storage

One of the most useful features of Joose is the builtin role Joose.Storage which gives easy JSON serialization and deserialization to all Joose objects. All you have to do to use this role is to add
does: Joose.Storage
to your class definition like this:
Class("Point", {
does: Joose.Storage,
has: {
x: {is: rw},
y: {is: rw},
otherPara: {
is: rw,
init: "stuff",
persistent: false
}
}
})

Now if you use the json2.js library avaible from json.org you can also say:
Joose.Storage.Unpacker.patchJSON();
... and magically when you use the JSON library all Joose object will be serialized when you call JSON.stringify and will be deserialized (become Joose objects of the correct type) again when you call JSON.parse.

This makes round-tripping between JavaScript and JSON very easy. For example this creates a point then serializes it and immediately deserializes the point again.
var point = JSON.parse(JSON.stringify(new Point({x: 10, y: 20})));
alert(point.getX())
With normal JSON the resulting object will not have any methods but with Joose.Storage you get a real object of class Point.

The best thing about Joose.Storage is that it also works for deeply nested objects and it even preserves identity when an objects occurs within the same structure multiple times. In the above example the attribute otherPara of class Point is declared as persistent: false. This means that the attribute will not be serialized. This makes sense for attributes which can't be serialized like references to DOM elements.

Here is the resulting JSON document for a nested structure of points:
JavaScript:
var p0 = new Geometry.Point({x: 10, y: 20})
var p1 = new Geometry.Point({x: 20, y: 30})

var test = {
a: p0,
b: p0,
c: p1
}

Resulting JSON:
{"a":
{"__CLASS__":"Point",
"__ID__":5,
"x":10,
"y":20},
"b":
{"__ID__":5},
"c":
{"__CLASS__":"Point",
"__ID__":6,
"x":20,
"y":30}}

Joose.Storage is ideal for sending object to the server using and then creating them again at a later point. Joose.Storage is also wire compatible with MooseX::Storage which is a Perl module for serialization of objects and there are efforts under way to make it compatible with jsonpickle which is a Python implementation of a similar concept.

Wednesday, August 6, 2008

Custom events in jQuery

Dion made a nice post about the power of custom events in jQuery. Here is his example converted to jQuery.

Monday, July 28, 2008

Total JavaScript Makeover

The new before and after page on the Joose wiki shows some simple examples of JavaScript code with and without Joose.
Obviously anybody, who has written more than twenty lines of JS in his/her life, either uses a class builder or at least utility functions to do these things.
Among those features of Joose that you won't find in your every day JS class builder are (all fancy meta stuff intentionally left out):
  • Automatic generation of accessor methods for attributes
  • Automatic generation of object initialization methods
  • Method modifiers (before, after, etc.)
  • Overriding of super class methods with access to the overriden method from the super class
  • Automatic serialization and deserialization of your (nested) objects to JSON (Joose.Storage)

Talking about Joose

Joose now has a mailing list. Feel free to join.

Getting Started Guide for Joose

There is now a getting started guide for Joose.

Friday, July 25, 2008

Version 0.99 of Joose released

We just released version 0.99 of Joose.
Download it here.

Joose is a self-hosting meta object system for JavaScript with support for classes, inheritance, mixins, traits, method modifiers and more. It makes object-oriented programming with JavaScript easy, declarative and very productive. The Joose meta-object system is multi-paradigm. It supports class-based and prototype-based programming styles as well as class-based inheritance and role-based extention.
The Joose framework has been successfully used in multiple production systems for four months now and has been proven to be very stable. Joose is being tested using an automated unit-test suite that is being run in all major browsers (Firefox, IE, Safari, Opera).

New stuff in Joose 0.99

  • Method modifiers can be used in roles
  • Joose.Storage now preserves object identities across serializations and deserializations. Joose.Storage is a role for automatic JSON stringification and restorations of Joose objects that is very powerful and easy to use. I'll write about it in another article.
  • Applying roles to instances no longer detaches the meta class for every role. Once is enough.
  • Joose.Gears now supports AJAX-Requests that are performent through Gears if available. This greatly reduces stress for applications that do a lot of polling
  • Various bug fixes
  • Intesive profiling and speed improvements
  • Pretty much all anonymous functions in Joose now have a name which makes debugging and profiling with firebug much easier.

What's next:

  • This version of Joose will be released as 1.0 when the documentation is ready
  • Specialized Plugin-Objects
  • Types and Type-Coercions (some support is already in Joose, see tests/16_types.js
Have fun with Joose!

Saturday, July 19, 2008

Class extention with roles and method modifiers

While working on blok I introduced a new feature to Joose that has proven to be a very powerful programming technique: Method modifiers used in roles.

Let me start with a quick introduction to those two concepts:

Method modifiers are declarative approach to JavaScript method wrapping techniques. They allow you to do stuff before or after a method is executed or to override a method and only call the method in the super class "on demand" using this.SUPER(). In the Joose cookbook a before method modifier is used to adjust a bank account balance using an overdraft account if neccessary:
Class("CheckingAccount", {
isa
: m.Account,
has
: {
overdraftAccount
: {
isa
: m.Account,
is: rw
}
},
before
: {
withdraw
: function (amount) {
var overdraftAmount = amount - this.getBalance()

if(this.overdraftAccount && overdraftAmount > 0) {
this.overdraftAccount.withdraw(overdraftAmount);
this.deposit(overdraftAmount);
}
}
}
})
Roles are a mixture between Java-Interfaces and and Ruby Mixins. They were originally called Traits but we like Role better :) They require that a class that implements them provides a set of methods but in contrast to traditional interfaces they may also export methods into the classes that implement them. Those methods may only use other methods provided or required by the role. That way a role can guarantee that the functionality it provides actually works in the destination class. A class that does a role may of course always choose to override methods provided by the role. This way roles give you all the power of multiple inheritance without the problems of mi.

Now to the real topic of this post: Method modifiers in roles.
Using method modifiers in roles creates a very natural and declarative way of solving a problem that is traditionally tackled with the decorator pattern:

(Dramatized) Java:
Window win = new ScrollingWindowDecorator(
new TabbedWindow
Decorator(
new ResizableWindow
Decorator(
new DraggableWindow
Decorator(
new Window("Window Name")))))
The decorator allows the dynamic composition of functionality by giving each decorator the chance to modify the behavior of the object when a method is called. Besides looking like Lisp because of all the )))) the decorator has one primary problem (or features depending on the view point): When window calls a method on itself, none of the methods of any of the decorator will be called.

Method modifying roles to the rescue. Consider this example: We want to model people who vary in their behavior when they say hello to somebody. Some people introduce themselves, some people are shy, some people stutter, all people say hello. The person class in Joose is easy:
Class("Person", {
methods: {
sayHello: function () {
print("Hello!")
}
}
})
The sayHello method prints "Hello!" when you call it. Now we use roles and method modifiers to attach extra functionality to the sayHello method. Lets start with the shy person:
Role("ShyPerson", {
before: {
sayHello: function () {
print("May I talk to you?")
}
}
})
Everytime before the ShyPerson says hello, she aks whether she may talk to you. Introductions follow the same principle:
Role("Introduction", {
after: {
sayHello: function () {
print("I am a Joose user.")
}
}
})
In our example people who stutter say "Stutter" before they say hello and then say everything twice. This example shows the implementation using the around and override method modifiers:
Role("Stuttering", {
around: {
// say it twice
sayHello: function (orig) {
orig()
orig()
}
},
override: {
// say Stutter and and say what was defined before
sayHello: function () {
print("Stutter")
this.SUPER()
}
}
})
Now, we'll define classes for two different persons with different behaviors:
Class("Eve", {
isa: Person,
does: [
Introduction,
ShyPerson
]
})

Class("Adam", {
isa: Person,
does: [
Introduction,
ShyPerson,
Stuttering
]
})
The does-keyword in the class declaration tells Joose that this class implements roles that follow in the declaration. So now Eve introduces herself and is shy. Adam has the same attributes but also stutters. Should Eve ever start to stutter, we can, of course, always later apply the Stuttering role to eve's instances: Stuttering.meta.apply(eve)

When you use the classes it looks like this (print is defined as somehow printing its arguments and attaching a new line):
var eve = new Eve();
eve.sayHello() // prints May I talk to you?\nHello!\nI am a Joose user.\n

var adam = new Adam();
adam.sayHello() // prints Stutter\nMay I talk to you?\nHello!\nI am a Joose user.\nMay I talk to you?\nHello!\nI am a Joose user.\n
Conclusion:
The above example shows how roles can be used to nicely attach extra functionality to classes using method modifiers. This pattern is especially useful if you need to augment a certain set of functionality without totally replacing the original methods which is a common phenomenon when you deal with GUI elements.

Improvements to Joose

Over the last couple of weeks most development time went into blok which is testing Joose in all possible directions which in turn leads to improvements to Joose:
  • Joose.Storage now preserves object identities across serializations and deserializations. Joose.Storage is a role for automatic JSON stringification and restorations of Joose objects that is very powerful and easy to use. I'll write about it in another article.
  • Applying roles to instances no longer detaches the meta class for every role. Once is enough.
  • Joose.Gears now supports AJAX-Requests that are performent through Gears if available. This greatly reduces stress for applications that do a lot of polling
  • Various bug fixes
  • Intesive profiling and speed improvements
  • Pretty much all anonymous functions in Joose now have a name which makes debugging and profiling with firebug much easier.
The by far biggest feature is method modifiers in roles. This is one of the most powerful constructs for in recent programming history and I'll write about it in another article :)

Wednesday, July 9, 2008

blok documents as a Google Gadget

Blok documents can now be embedded as a Google Gadget (as can thus be embedded into google spreadsheets). The feature is highly experimental right now, but will get better. If you have a document with the url http://blok.appspot.com/?id=efdc360d2dd2b3f0ed24b156e4751bb035fee0a4, change this to http://blok.appspot.com/gadget.xml?id=efdc360d2dd2b3f0ed24b156e4751bb035fee0a4 and you can embed the url as a google gadget.

You can check out an example document at this url: http://spreadsheets.google.com/pub?key=p8nd1kNNlWNuTmZ3XLUADEg

Sunday, July 6, 2008

blok now uses Google Gears where available

blok now uses the Google Gears HttpRequest API to make the synchronization calls to the server if gears is installed on the client. This makes the GUI feel a little more responsive. Next up is using Gears to offload the rest of the syncing work (primarily JSON stringification and parsing) that can be done in gears (everything that does not need to manipulate the DOM.
Joose supports a transparent method to offload hard work into Gears workers that was even talked about on the Google Gears blog. While the method used to be rather basic I'm enhancing it now so that you can use the Timer and HttpRequest api transparently in your code without having to care about whether google gears is actually available (work is done in the main thread if gears is not installed).

Friday, July 4, 2008

Changed Repository to Google Code

I moved the Joose SVN repository back to the Joose's Google Code site.
Joose used to live in the Moose repository which was great but didn't have a great function to view the source code without checking it out of the repository.
I'd recommend looking at the class that represents the rectangle shapes in the blok application. It really shows how roles can be used as a very flexible extention mechanism.