EcmaScript Edition 5 is final

April 9th, 2009

After a lot of back and forth in the TC and the failure of ES4 the TC was focused on ES3.1. The final spec for ES3.1 is now called EcmaScript, Fifth Edition.

The most exciting thing in ES5 is that it finally standardize getters and setters. It also allows us to control the enumerability as well as whether properties should be read only etc. ES5 also adds a few other things like the array extras from Mozilla.

New Explorer Canvas Release

March 22nd, 2009

Over at the newly created Explorer Canvas Blog we announced the new release.

Playing around with WebKit Animations

February 20th, 2009

Ever since WebKit started to introduce all these fancy new CSS properties like 2D and 3D transformations, transitions and declarative animations I’ve been drooling like a script kiddie from the year 2000. I’ve been thinking about how I can use them in some Google property but unfortunately the whole world is not using nightly builds of WebKit so I’m pretty limited to just playing around at home. Well, platying around home is not
exactly what I did. Most of the time I was actually playing on the bus going home from work.

I’ve been playing around doing a KeyNote like animation done with CSS and some JS to hook up the necessary events. The animation is kind of like a deck of cards. When you go to the next one the current one zooms in and fades out,
symbolizing getting closer to the viewer. The next card then zooms and fades in from the back and to give a fancy effect ;-)

V1

Example 1 (use left and right arrow keys to go between the cards.

I started off playing around with the @keyframes rule. This is the CSS animation that gives you most control and it should be good enough to be able to replace most of your js animations. I believe JS libraries should be able to use the CSS animation internally as long as no code depends on ” any animation” events except start and begin.

The CSS animation allows you to set the animation-name at the time you want to start your animation. You can set up multiple keypoints at different intervals but for the simplest case you only need to set the from (0%) and to (100%) frames.

For the animation I had in mind I needed 4 animations. fade-in-backwards, fade-out-backwards, fade-in-forwards and fade-out-forwards. These are extremely simple and I was very tempted to create these using the CSSOM but I never went that far.

To play the animation forward I set the animation-name of the current card to fade-out-forward and the next card to fade-in-forward (and the fade-*-backward for animation backwards).

The CSS animations has a few drawbacks. One of them is that when the animation is finished it is pretty cumbersome to freeze the state. One way to achieve the freezing is to listen to the window.onwebkitanimationend event , check the
animationName of the event, read the computed style and apply that. The problem with this is that I either iterate over all CSS properties used in the to (100%) keyframe or I manually keep track of the properties I want to freeze. I ended up
manually setting the properties because I was laze. This does not scale well of course so if you are serious about freezing your animations I would recommend writing functions to freeze the animation (you will need to be able to unfreeze
it if you want to animate it again).

I can think of two other drawbacks. One is mentioned in the spec proposal and that is the ability to pause the animation. The spec proposal currently supports this but they are considering removing it. If they remove it the user will have to write some non trivial js to freeze the state again (same thing as I talked about before). I’m not even sure how resuming would work since I don’t think there is a way to set the time for the animation.

V2

Example 2

It turned out that my use case is actually a transition (surprise) and for transitions, CSS transitions are much better suited.

Transitions allow you to change a CSS property (any property that supports transitions) and it will animate the property when changed. For example, if you say that “width” should be a transition-property, setting the width will animate the width from its old width to the new width. I cannot emphezise enough how useful this property is. Please reread this paragraph and makes sure you get it :-) Now how many lines of js do you need to make your elements fade in and out when you show and hide them? None, it is easily done with one line of CSS (if
you use opacity to hide them that is).

So back to the KeyNote like demo. The idea here is to set all the coming cards to zoomed out and totally transparent and all the previous cards to zoomed in and transparent. Now you only need to change which element is current by setting the zoom to 100% and the opacity to 1. Done!

That is not entirely true, I also updated the class name of the previous and next card.

V3

Example 3

This is an iteration on the previous one. Instead of defining .next, .current and .previous classes I realized I could use the :target CSS selector in combination with the next sibling selector. The :target selector matches any
element with the same id as the hash fragment of the URL. This is mostly used for highlighing the target of an internal anchor that was clicked but it can be used for other more fancy things (like tab panes for example).

When the page loads I needed to ensure that the URL contained a hash fragment and if it didn’t I replaced the URL with one that did. Also, I needed to add some code to sync the current card with the hash, allowing the user to bookmark
the correct card. A feature that should be part of any sane web app.

Conclusion

I cannot wait till we can use things like this in all browsers. It will surely make the web a richer experience. Once again, I’d like to thank the WebKit team for a totally excellent web browser and for pushing the web foward. I don’t know
what I would do without you :-)

Offline Gmail

February 3rd, 2009

Last week we launched Offline Gmail. After releasing Gears I moved to the Gmail team to work on Offline Gmail. I think it was pretty obvious that we were working on this and Offline Gmail was the first and possibly the hardest task we wanted to be able to solve with Gears.

A lot of things have been said about Offline Gmail but not too much has been said about how it was implemented. If there is any interest I’ll take questions and answer those in a follow up blog post.

One thing that I would like to add is that even though the UI for enabling the offline lab is only available in English you can still get Offline Gmail in any language Gmail supports. Here is how:

  1. Change your language to English
  2. Go to Labs and enable the Offline lab.
  3. Switch back to your language of choice.
  4. Enable offline from the offline settings tab or from the link next to your user name in the upper right corner.

Using catch-alls to implement super in SpiderMonkey

November 27th, 2008

Another thing that always been bothering me about OOP in JS is that calling super is such a pain. Some libraries do ugly hacks like checking the source (by calling toString on their constructor and method function objects) and then wrap the original function in another function that encapsulates a variable called super. Other libraries do even worse things like rewriting the code of the function and eval’ing it. These hacks work in most cases (not in Opera for mobile phones) but it is very inefficient.

Yesterday morning (when reading a lengthy email to es-discuss) I realized that I could probably use catch-alls to emulate super. Catch-alls is a SpiderMonkey feature that allows an object to have a method that will be called when a non existing method is called. Catch-alls are proposed for ES-Harmony. The idea I had was to create a super object that uses the catch-all mechanism to call the method on the super class with this bound to the current object. I wanted to achieve something like this:

function B() {
  supr(1, 2, 3);
  this.method = function(x) {
    supr.method(x);
    ...
  };
}
inherits(B, A);

Instead of having to write:

function B() {
  A.call(this, 1, 2, 3);
  this.method = function(x) {
    A.prototype.method.call(this, x);
    ...
  };
}
inherits(B, A);

So supr needs to be a function which has the __noSuchMethod__ method set to call the method of the [[Prototype]] object.

Take one:

function B() {
  var self = this;
  var supr = function() {
    return A.apply(self, arguments);
  };
  supr.__noSuchMehod__ = function(name, args) {
    return A.prototype[name].apply(self, args);
  };

  supr(1, 2, 3);
  this.method = function(x) {
    supr.method(x);
    ...
  };
}
inherits(B, A);

Lets take a look at the inherits function. It is something all js dev heads should have in their repertoire. It is extremely useful and it allows you to declare inheritance without having to create an instance of the super class.

function inherits(child, parent) {
  var f = function() {};
  f.prototype = parent.prototype;
  child.prototype = new f;
  child.prototype.constructor = child;
  child.superClass = parent;
}

The last two lines are important because JS does not maintain the mapping to the constructor and by adding the superClass property it allows us to easily get access to the parent constructor.

With the innards of the inherits function known combined with take one above we can write a helper function that makes creating the supr object a lot easier.

function createSuper(self, opt_constr) {
  var constr = opt_constr || arguments.callee.caller;
  function supr() {
    return constr.superClass.apply(self, arguments);
  };
  supr.__noSuchMethod__ = function(name, args) {
    if (typeof constr.superClass.prototype[name] == 'function') {
      return constr.superClass.prototype[name].apply(self, args);
    }
    throw Error('No such method, ' + name);
  };
  return supr;
}

And then we can use this.

function A(x) {
  print('In A constructor, x = ' + x);
}
A.prototype.a = function(x) {
  print('In A.prototype.a, x = ' + x);
};

function B(x) {
  print('In B constructor');
  var supr = createSuper(this);

  supr(x || 'From B');
  var className = 'B';
  this.a = function(x) {
    print('In ' + className + '.a');
    supr.a(1);
  };
}
inherits(B, A);

function C(x) {
  print('In C constructor');
  var supr = createSuper(this);

  supr(x || 'From C');
}
inherits(C, B);
C.prototype.a = function() {
  var supr = createSuper(this, C);
  print('In ' + 'C' + '.a');
  supr.a('supr.a called from a c object');
};

print('Creating an instance of B');
b = new B;
b.a(2);

print('');
print('Creating an instance of C');
c = new C;
c.a();

Try this (Firefox only)

This works because supr is recreated for every constructor and is bound lexically Don’t do this.supr = supr and think you can reuse it. It will not work. This does not require that you put the methods that needs super inside the constructor but if you don’t you will have to call createSuper and pass in your constructor from your method which is not very efficient and it is hardly much better than using the straight forward way to call super by just getting the function of the super class prototype and call it by name (A.prototype.a.call(this, 1)).

Conclusion

Once again I find that adding code to make things simpler in JS is unsuccessful. The costs for adding better ways to do things don’t pay for itself. (Except for the inherits function of course.)

Instance private, class private, package and friends

November 14th, 2008

Update: This is flawed. See details at the end.

This post was inspired by a post that Robert Nyman wrote a while back. At the same time I was thinking about how to achieve private fields without the memory issues.

JavaScript does not have private members as understood by a lot of other object oriented programming languages. However it can use closures to achieve the same effect. Below is a very typical code sample.

function Cartman() {
  var secret = 'Tea party';
  this.guessSecret = function(guess) {
    return guess == secret;
  };
}

This is pretty straight forward and works because we define the public method in the scope of the local variable which now works like a private property. There are a pros and cons with this pattern:

Pros: Simple and easy to understand.

Cons: Very memory hungry since every instance needs its own function to encapsulate the local vars.

Therefore most libraries that are object heavy uses a naming convention for private fields. The most common convention is to prefix the field with an underscore.

function Cartman() {
  this._secret = 'Tea party';
}

Cartman.prototype.guessSecret = function(guess) {
  return guess == this._secret;
};

Now all instances can share the methods but we lost the integrity. Anyone can read _secret of an instance.

I’ve been playing around with hybrid models that allows methods to be shared but still allow real private members.

My first idea was to use a closure outside the actual constructor and define a key there. Then basically store the private state in an object that is guarded by that key. This turns out to change the model from instance private to class private. This means that all instances of a class can access the private state of all other instances of that class. Some OOP do this intentionally. Java does this for example.

The code for this quickly gets ugly but below is a working example.

// Define variable outside anonymous block. Will be set inside the block.
var A;
(function() {
  var KEY = {};

  /**
   * Helper function to get the private state object.
   * @param {!Object} obj The object to get the private state for.
   * @return {!Object} The private state object.
   */
  function getPrivate(obj) {
    return obj._getPrivateWithKey(KEY);
  }

  /**
   * Store the private state object in a closure.
   * @param {!Object} obj The object
   * @param {!Object} state The state.
   */
  function setPrivate(obj, state) {
    // Add a convenience method.
    obj._getPrivateWithKey = function(key) {
      if (key === KEY) {
        return state;
      }
      throw Error('Permission denied');
    };
  }

  // Set the external variable here.
  A = function (a) {
    var P = {
      a: a
    };
    setPrivate(this, P);
  };

  A.prototype.getA = function() {
    return getPrivate(this).a;
  };
})();

Try it.

This works because the object is associated with the key inside setPrivate using a closure. The function getPrivate which uses the KEY is only visible inside the anonymous function scope and therefore only code inside the anonymous function can get access to the private state.

This actually leads to any code inside the anonymous function being able to see the private state of an object. You can therefore use this concept to allow different classes defined within the same anonymous function scope to see each others private state. This can be treated as a sealed package — a package that cannot be reopened after it has been closed.

We can take this concept one step further and add support for C++ style friends by giving away our key to someone else. Something like:

var A;
(function() {
  var KEY = {};
  A = ...;

  var friendKeys = {};
  A.addFriend = function(id, key) {
    friendKeys[id] = key;
  };

  function getFriendPrivate(obj, id) {
    return obj._getPrivateWithKey(friendKeys[id]);
  }

  A.prototype.accessFriendPrivate = function(obj) {
    return getFriendPrivate(obj).b;
  };
})();

var B;
(function() {
  var KEY = {};
  B = ...;
  A.addFriend('B', KEY);
})();

Try it.

Now instances of A can access the private state of instances of B.

Conclusion

Is this really useful? I would say no. It adds too much boiler plate code without enough real gain. A lot of people try to apply known concepts from languages like Java and apply them to JavaScript. If you really need to be able to hide the state then I would use the instance private pattern first used in this post. It is easy to write and easy to understand and does not have a lot of boiler plate code. However, I would only use it where hiding the state really matters. In most cases it doesn’t. For example, Gmail was written without any true private members. We just use a naming convention.

This also brings up a related topic which is using JS as an object capability language and Doug Crockford made an excellent presentation about this a while back.

Update

henrah pointed out that this model is flawed since the key leaks. Anyone can override _getPrivateWithKey to get access to the key.

Just Married

October 12th, 2008

Toi Sin & Erik, October 4th 2008

Photo by our friend Stella Loh.

Google Chrome

September 2nd, 2008

I guess you all have downloaded Chrome already. If not, what are you waiting for?

I’d like to congratulate my friends who have been working so hard on this. Congratulations Glen and Ojan.

Also, I’d like to add that Chrome is totally awesome, and I’m not saying that because I work at Google. I’m saying that because it is the simple truth ;-)

IE8 and box-sizing

March 10th, 2008

One of my top feature request for IE8 was for it to support box-sizing. I’m happy to see that IE8 does support box-sizing although it has a annoying quirk. The DOM property name is not correct. The rule for translating CSS property names to DOM property names is to replace a dash followed by a character by the uppercase character. Using JavaScript it can be written like this:

function toCamelCase(s) {
  return s.replace(/\-(\w)/g, function(_, c) {
    return c.toUpperCase();
  });
}

Since the CSS property for box-sizing in IE8 is -ms-box-sizing the DOM property name is should be MsBoxSizing. The -ms- prefix is a defacto standard for non standard CSS properties and Firefox, WebKit and Opera has tons of -moz-, -webkit- and -o- respectively.

We would therefore have to add a browser check in our function above:

function toCamelCase(s) {
  return s.replace(/\-(\w)/g, function(_, c, i) {
    if (MSIE && i == 0) {
      return c;
    }
    return c.toUpperCase();
  });
}

Not only does this require more code it also adds a mental obstacle and one more quirk to add to the already overflowing quirk-filled brains of developers world wide.

The Good, the Bad and the Ugly

March 6th, 2008

The Good

Attribute handling in the DOM is finally working. MS said that this was one of the hardest things to fix and yet they did it.

hashchange events simplify history management. I wish they implemented more of the HTML5 proposals when it comes to history state management but getting an event when the hash changes is so much better than what we have today.

Acid2

querySelector and querySelectorAll… nuf said

JScript is faster. There is a lot of room for improvements but this is a big step in the right direction.

postMessage. Now that all new browsers support it we can finally get rid of all those ugly, complicated and slow cross domain hacks that tons of sites rely on today.

Standard mode as good as possible by default. No need to opt in to get the best possible renderer.

Changes to namespaces in XHTML allowing third party to, in theory, implement binary behaviors for SVG embedded in XHTML.

ARIA support. I remember the hoops we had to go through to get Bindows 508 compliant. If there was only ARIA support back then it would have saved several months worth of frustrating work.

The Bad

VML is not currently supportd in IE8 mode. This would not be so bad if canvas or SVG was supported but today sites have come to rely on being able to use vector graphics in web pages. MS says “Layout and rendering behaviors, proprietary features upon which VML is built, are not yet implemented in IE8 standards mode. Look for this feature in a future beta release.”

No opacity, rgba() nor any rounded corners in sight.

Yet another browser check needed. We used to only need to check the user agent, then we also had to check the document.compatMode and now we have to also check document.documentMode. Would it not have made more sense to just return MSIE7 in the user agent if IE8 is operating in IE7 mode?

No bug fixes to JScript. MS has an excellent paper covering their deviations from ES3 but yet they managed to improve on that situation. MS is waiting in ES3.1 but I think it would have been safe to fix some of these issues already. ES3.1 is on the fast track but I doubt there is room for any differences to what is already available in WebKit, Firefox and Opera today (which have tons of ES3.1 features and bug fixes today).

Still no way to get the computed style.

The Ugly

HTML5, and the W3C Web App group has a proposed standard for doing cross site XHR that is implemented in WebKit, Firefox (and Opera?). Yet, Microsoft introduces XDomainRequest which is very crippled.

MS built their DOM storage implementation on top of their old persistence behavior which uses XML files to store the data and since it does disk writes MS decided that their implementation would not be good enough to follow the proposed spec they made the whole API asynchronous. DOM storage is implemented in WebKit, Firefox and Opera.

Where is the DOM? MS kept asking what people wanted and every list I’ve seen has included DOM Level 2 events and DOM level 2 in general.

Acid3. 16/100 is not acceptable