Read the latest news on the Cappuccino reddit.

Randy Luecke Becomes a Committer

March 12th, 2010

A little late to post this, but everyone in the Cappuccino has loved the work Randy (Me1000) has been doing on CPTableView. Thanks to his hard work and significant contributions, the table view component in Cappuccino is now a force to be reckoned with. So we’re proud to have Randy as our latest Cappuccino committer, and we’re looking forward to the table view features still to come.

Randy also has his own Cappuccino app he’s been developing called TimeTable. It’s a time tracking app thats set to launch soon, so keep an eye out!

Internet Explorer: Global Variables, and Stack Overflows

March 1st, 2010

Stack overflow at line: 0

Every once in a while, you stumble upon a particularly strange bug. A bug that seems to defy the rules of space-time. A bug that makes you pull your hair out for days. A bug that almost certainly includes Internet Explorer. This was one of those bugs for me, and since I haven’t found a lot of information out there even now that I know what the problem was, I wanted to write it up for posterity.

It starts with what looks like a relatively benign function, that we’ll call recurse:


window.recurse = function(times)
{
    if (times !== 0)
        recurse(times - 1);
}

recurse(13);

If you pass in the magic number 13 (or anything higher), this recursion is going to fail with our stack overflow pop up. No problem, you say? You’ve fought Internet Explorer before, and you know how to get down to business. Fire up the trusty IE 8 debugger and get to work! Unfortunately for you, the debugger won’t be triggered. Just a pop up for you. If you’re feeling extra ambitious, maybe you’ll try installing Visual Studio and hooking up the advanced debugger directly to IE; I did. No such luck.

I should mention that the code above wasn’t what forced me to investigate this bug. I’m not usually in the habit of writing recursive functions that don’t actually do anything. And when your code base is tens of thousands of lines long, and your coworker has pushed a
couple thousand new lines of code (which radically alter the load process), tracking down any problem without a debugger starts to get hairy. At one point in the process, I actually stepped line by line through every single new line of code, certain I’d track down the bug. I didn’t, because not only does IE not trigger the normal exception mechanism, it doesn’t even report the error until after any waiting script executions are finished. Fun.

Thankfully, my neighbor works at Microsoft, so I was able to get an inside look into the issue. That’s where our test function comes in (thanks Microsoft). Let’s get back to it:


var recurse = function(times)
{
    if (times !== 0)
        recurse(times - 1);
}

recurse(13);
recurse(10000);

Our new version works. Can you spot the difference? We’re using a “local” (but really global considering our current scope) variable here, instead of assigning the function to a property on the window object. This tells us that it has something to do with the window “host” object, but it isn’t the whole piece of the puzzle just yet.


(function(){
    var recurse = function(times)
    {
        if (times !== 0)
            recurse(times - 1);
    }

    //we won't have access outside to recurse, so add a global ref
    window.recurse = recurse;
})();

recurse(13);

This test also works, and is pretty much the last piece of the puzzle. From this we can see that simply assigning a variable through the window object isn’t the problem, the problem is actually recursing through that variable.

In the block above, the recursion is happening through the local var, not the global reference, and so it isn’t triggering the bug. To prove that this is the case, let’s try the opposite test:


(function(){
    var r = function(times)
    {
        if (times !== 0)
            recurse(times - 1);
    }

    //we won't have access outside to recurse, so add a global ref
    window.recurse = r;
})();

recurse(13);

Here, we’re doing the recursion through the global reference, and as we expected it fails. So, the lesson to learn here is that any recursion that happens through the window object is limited to a stack depth of 12. If there was a tl;dr; to this post, it would be that.

To dig just a little bit deeper into some of the oddities of what’s going on here (and how it impacted Cappuccino), you’ll want to see this unbelievably strange (but not technically incorrect) behavior:


window === window;           //true
window.window === window;    //false

function global(){
    return (function(){return this;})();
}

global() === window;         //true
global().window === window;  //false

Technically, the behavior of the window object isn’t defined by ECMAScript or any browser standard; it’s a native object provided by the browser to the runtime environment. As a result, even though IE’s behavior here is strange, and the opposite of all other major browsers, it isn’t technically wrong. It’s absolutely terrible, though.

Why did we have this problem in the first place? To answer that, you need to know a bit about CommonJS modules. In the CommonJS “spec” modules have their own scope, and don’t export their vars as globals to the outside world. Instead, the module loader passes in an “exports” object, and the module author assigns properties to that object. Another way to put it would be to say that the public API of any module has to be explicitly created by assigning methods to the exports object.

In addition to Cappuccino, we’re also the authors of Narwhal, the most popular implementation of the CommonJS spec. We’ve already migrated most of our tools to run on top of Narwhal, and we’re continuing to improve the integration between Objective-J and Narwhal. Part of that means changing some of our code to use the exports technique, and using that same code in the browser.

What we ended up with was something like this:


var exports = {};
(function(global, exports){

    //lots of methods...

    function objj_msgSend(){
        //do some stuff;
    }

    //lots of exports...
    exports.objj_msgSend = objj_msgSend;

    // make exports global
    for (var export in exports)
        if (exports.hasOwnProperty(export))
            global[export] = exports[export];

})(window, exports)

The final loop assigns the exports to the global scope, since that’s how Objective-J code is expected to run. This last step was the cause of all of our problems, because as you can see, we’re creating all global methods on the window object, which means all calls to them are going to go through the host object, and be subject to our exceptionally low recursion limit.

Our first fix looked like this:


    for (var export in exports)
        if (exports.hasOwnProperty(export))
            eval(export +" = global[""+export+""];");

The eval creates a global implicitly, rather than explicitly, which doesn’t trigger the trip through the host object. We explored a few different ways to get around the bug, including working with Microsoft, but found no other viable solution.

Rather than ship this code in Cappuccino 0.8, though, we decided to take a step back and re-examine our initial requirements. The desire to strictly adhere to the CommonJS proposal was requiring that our code become more complex and harder to maintain, so we dropped that requirement.

The final version of the code is almost exactly the same, except rather than doing things like global.foo = function(){}, we’re simply using implicit global creation directly. This is more in line with the way all existing JavaScript runtimes actually work. It’s also the way Narwhal works, and probably the way CommonJS should work.

I want to give another thank you to all the folks at Microsoft who helped us track down the problem and provided us with a simple test case that reproduced the problem. They were quite helpful, and we (along with all of our users) appreciate it. Now hopefully we’ll see this issue addressed in IE9, along with a faster JavaScript engine :) .

Nick Small Becomes a Cappuccino Committer

November 29th, 2009

A big congratulations to nciagra for becoming a committer to the Cappuccino repository. While we’ve always been taking in contributions from Nick and other community members, this represents the first time someone outside 280 North has been granted access to commit directly to the repo.

Anyone following Cappuccino can see that Nick has been a valuable member of the community. He’s always offering help in the IRC channel and on the mailing list, and he’s also the most active contributor outside 280 North. On top of all that, he’s been working on some exciting new ideas for Cappuccino, some of which we hope to fold into the main repository in the coming months.

So congratulations to Nick! And as Cappuccino continues to progress, we look forward to adding even more committers to the project.

Just One File with Cappuccino 0.8

November 11th, 2009

The entire 280 crew just got back from an awesome time at JSConf EU in Berlin, where we got to show off some of the cool new developments coming with Cappuccino 0.8. I wanted to take the time to share one in particular in more depth here: image spriting.

The Problem with Spriting

Image spriting is the act of taking all the images in your app (or framework, or library, or whatever) and combining them down to one single image. This has the advantages of being smaller (since each individual image has overhead associated with the format), as well as allowing you to grab it from your server with one request:

Traditional Spriting

This is faster in an absolute sense, but even more so psychologically since it allows you to show the contents of your app faster without having all the images “flash in” later. Cappuccino currently uses a similar technique with the source code in your application: concatenating it all together and minifying it, but up until now we’ve had no automatic, or built-in, support for spriting, you’ve instead had to do it entirely yourself. And truthfully, no framework has really good support for this.

This is because the fundamental problem with spriting today is that the process isn’t really automated and the results are thus subpar. Sure, there are scripts which will put images together for you, but they all require you to configure them first and to update them as your use of the images in question changes. This is because traditional spriting is dependent on how you use your images. Whether you choose to repeat, stretch, scale, or even draw to a canvas affects which images can be sprited together, and even which can’t be sprited at all. This has a number of unfortunate side effects:

  • Rarely do you actually end up with just one image: Instead, you can end up with 2, 3, or even more. This is because images have to be “grouped” by their use. For example, vertically repeating images can be sprited together, but not with horizontally repeating images.
  • You may have to actually change your code: Since images are being mutated, the code you write needs to take into account these new images. If you are lucky you have a system that is relatively good at doing this for you. However, if you decide to use an image in a new way (such as drawing it to a canvas), you either have to update your configuration files or choose to code it differently. This is easy to forget.
  • Your images are still shipped separately from your code: Even in the best case where you are lucky enough to successfully sprite all your images together, you still have to wait for them separately from when your code is ready, potentially leading to noticeable delays from latency, or a “flash in” effect.
  • Inflexible due to loss of data: There exist cases where your code is meant to be used by others, such as with libraries and frameworks. In this case, images can’t be used in any way other than how you intended them to if they are sprited, because the original images are gone or would require a redundant second download.

So unfortunately there is currently no good one-size-fits-all solution for image spriting the way there is with “code spriting”. All of them require the user to actually become involved in the optimization process, and even still can produce less than stellar results. This is clearly not a solution that can scale, and most everyone agrees to this.

But we’re hoping to change this with the release of Cappuccino 0.8, as we’re introducing a whole new, completely cross-platform, way to sprite: base64 images. By encoding images as base64, we create a lossless text representation of images, allowing us not only to use them in whatever way we please, but to actually ship them with the code:

There are many advantages to this:

  • One file, guaranteed: All images can always be sprited together regardless of how you plan to use them, and can be included with the actual source code. This has the added benefit that gzip can work its magic on the entirety of your web app as one, producing better results.
  • No need to ever modify code or configuration files: Since we’ve eliminated the ambiguous part of spriting images, the Cappuccino build tools are able to perform this optimization on your code automatically without tedious configuration files or having to “learn” how to sprite.

Yes, This Works in IE 6 and 7.

I’m sure most people are wondering how we are pulling this off in versions of IE before 8, since they do not support data URLs. Notice that earlier I didn’t specifically mention data URLs though, I instead only referred to the more broad technology of base64 images. As it turns out, IE has had support for base64 images since version 6 (!) with a little-known technology called MHTML. MHTML allows you place all your resources in one “resources” file, which incidentally can be any file in your website… including the same file that contains all your code.

Cappuccino is already smart enough to be able to automatically download and use different code depending on what browser is being used (and with no server configuration), so we now simply ship data URL versions of this technique to modern browsers, and MHTML versions to older copies of IE:

Cappuccino Spriting

This is a very exciting feature for us. This has been a weak point in Cappuccino and its nice to finally have a solution that not only works, but is drop dead simple to use. Our tests have been proven incredibly promising, giving us the fastest load times we’ve ever seen with Cappuccino, and absolutely fantastic perceived speed as well. Our tools have all been honed to use this at every level: Apps, frameworks, and themes will automatically sprite your images for you.

This is just one of the many enhancements coming with Cappuccino 0.8, and the best part is as usual you won’t have to change a single line of code to get all the benefits.

Cappuccino in Checkout 3

October 6th, 2009

Sofa just released the third version of their award winning point of sale software, Checkout. Chances are if you’ve ever seen a Mac behind the counter when you’ve made a purchase, it was running Checkout. Version 3 adds lots of new features, but what’s really cool is that they’ve added a new web component built on top of Cappuccino called Enstore that allows you to take your physical store and put it completely online. For Enstore, Sofa wanted a truly desktop like experience for managing and creating online stores, and you really have to try it yourself to see how amazing it feels.

From a technology perspective, Enstore is a real milestone as the UI was built almost entirely using nib2cib, showing that Cappuccino doesn’t just let you build apps faster, but also creates drop dead stunning results.

Klaas Pieter has written up an excellent blog post about his experiences creating Enstore at Sofa where you can learn more, and a special thanks to him as well for contributing a lot of bug fixes along the way!

Push with Cappuccino and Tornado

October 5th, 2009

Elias Klughammer has taken the time to put together a demo of using the new Tornado web server to bring push to Cappuccino applications. Tornado is a brand new non-blocking server recently open sourced by Facebook which was built to deal with the high intensity demands of FriendFeed. When combined with Cappuccino, the results are pretty impressive:

Check out the project on GitHub to start hacking on your own real time Cappuccino services!

Download

Cappuccino and Objective-J are licensed under the LGPL. For more information, see our licensing page.

Copyright © 2009 - 280 North, Inc. Cappuccino and Objective-J are registered Trademarks of 280 North. Logo by Sofa. Hosting by Slicehost.