Good news! David Flanagan recently announced the fifth edition of his book Javascript: the Definitive Guide, something I've been eagerly awaiting for a year or two now, being the only book about the language to date that I have found worth buying. Amazon is accepting pre-orders already, and it seems it will be shipping by early August.
The first part of the book deals with the core language, as described by the ecmascript standard. Personally, I am most of all looking forward to the second part, which focuses on client side applications of javascript -- my own primary interest in the language. David's teaser promises chapters in contexts of SVG, the <canvas> tag, XML processing and scripting HTTP and Flash. If they are even close to the very high standards of the previous (fourth) edition from 2001, it will be an excellent read and all-round reference work to have at hand.
Webby thoughts, most about around interesting applications of ecmascript in relation to other open web standards. I live in Mountain View, California, and spend some of my spare time co-maintaining Greasemonkey together with Anthony Lieuallen.
2006-05-16
2006-05-08
Avoiding javascript leakage
David Baron recently made a good leak detection tool for tracking down leaky extensions, web pages, javascript libraries and the like. Much as I suspected, my own blog template is a sieve -- mostly for using the Google Maps API v1, but the calendar, some small details in my own code, and even in jQuery, which I use to toss in Blogger comment faces on my posts nowadays, leaks references to objects that ought to have been garbage collected.
Avoiding leakage is one of the better marks of differenting excellent programmers from good ones. Or, if you have high standards (you might be Joel Spolsky, for instance, and only afford yourself the very cream of the crop). In a typical browser environment, you rarely notice a leak unless you really look for it, and even then, it has typically been a bit of a hassle, and lots of labour tracking them. Leak Monitor steps in, solving that problem.
Web page code that results in memory leaks in the browser is in a way not really a bug in the web page per se -- non-broken browsers should always catch and dispose of the garbage we generate from user code from the messy steamping pile of dung that is the web. The hallmark of a great browser is polishing up the chaotic and broken web, making it look polished and behave well, giving us a pleasant browsing experience. Which is difficult. Very difficult. A browser that fails to collect the garbage that we strew about is a buggy browser. It is a bit unfortunate that most browsers don't do a very good job about leaky web page code. Typically including our favourites; present day Firefox still has these issues, Internet Explorer too.
So it's worth the effort writing leak free code, registering matching unload handlers to unregister the event listeners you add to a page, for instance. Especially in code meant for others to use, such as libraries like Google Maps, or jQuery, Dojo and so on, where end users are both unlikely to notice them and even less likely to be able to fix or bypass them. It's no coincidence the Google Maps v2 API supplies a method meant to be called on page unload, to unregister all the event handlers the API sets up of its own accord. If you write v2 Maps applications, be sure to use it.
I'm hoping to eventually find some time to shape up my own blog, perhaps rewrite some parts of the calendar code and maybe repackaging a zip file of that with additional bugfixes (as the upstream maintainer seems to have treated their GPL:ed version of the code a non-maintained dead end). I also hope we will see leak fixed versions of the Google Toolbar, the Web Development Toolbar and Flashblock, now that it has become so easy spotting the culprits -- not only do you get to see which objects are leaked, you also get source filenames and line numbers, so it's not really even the matter of tracking down where the bad things happen.
I'd like to share a particularly useful piece of code I picked up on the Greasemonkey list a while ago, which has ended up mostly everywhere I handle events these days. It might need a bit of reshaping to fit an extension context, but the principle is the same. The original class was called EventManager, but I opted for something that would not be even more carpal tunnel syndrome typing than the original DOM API -- so below it's renamed EventMgr:
Usage is simple: where you previously wrote
The class assumes a DOM compliant browser (so it's not IE compatible, for instance), but I have had very good use for it in my user scripts, where the code gets to run on mostly any page I visit, across the entire web -- which can add up to lots of leakage in the long run, if you write sloppy code. But any event handler you add using the above method also gets removed as you leave the page without your lifting a finger.
Even before elder mozillan wizards squash the bugs deep down near the firefox core.
Avoiding leakage is one of the better marks of differenting excellent programmers from good ones. Or, if you have high standards (you might be Joel Spolsky, for instance, and only afford yourself the very cream of the crop). In a typical browser environment, you rarely notice a leak unless you really look for it, and even then, it has typically been a bit of a hassle, and lots of labour tracking them. Leak Monitor steps in, solving that problem.
Web page code that results in memory leaks in the browser is in a way not really a bug in the web page per se -- non-broken browsers should always catch and dispose of the garbage we generate from user code from the messy steamping pile of dung that is the web. The hallmark of a great browser is polishing up the chaotic and broken web, making it look polished and behave well, giving us a pleasant browsing experience. Which is difficult. Very difficult. A browser that fails to collect the garbage that we strew about is a buggy browser. It is a bit unfortunate that most browsers don't do a very good job about leaky web page code. Typically including our favourites; present day Firefox still has these issues, Internet Explorer too.
So it's worth the effort writing leak free code, registering matching unload handlers to unregister the event listeners you add to a page, for instance. Especially in code meant for others to use, such as libraries like Google Maps, or jQuery, Dojo and so on, where end users are both unlikely to notice them and even less likely to be able to fix or bypass them. It's no coincidence the Google Maps v2 API supplies a method meant to be called on page unload, to unregister all the event handlers the API sets up of its own accord. If you write v2 Maps applications, be sure to use it.
I'm hoping to eventually find some time to shape up my own blog, perhaps rewrite some parts of the calendar code and maybe repackaging a zip file of that with additional bugfixes (as the upstream maintainer seems to have treated their GPL:ed version of the code a non-maintained dead end). I also hope we will see leak fixed versions of the Google Toolbar, the Web Development Toolbar and Flashblock, now that it has become so easy spotting the culprits -- not only do you get to see which objects are leaked, you also get source filenames and line numbers, so it's not really even the matter of tracking down where the bad things happen.
I'd like to share a particularly useful piece of code I picked up on the Greasemonkey list a while ago, which has ended up mostly everywhere I handle events these days. It might need a bit of reshaping to fit an extension context, but the principle is the same. The original class was called EventManager, but I opted for something that would not be even more carpal tunnel syndrome typing than the original DOM API -- so below it's renamed EventMgr:
EventMgr = // avoid leaking event handlers
{
_registry:null,
initialize:function() {
if(this._registry == null) {
this._registry = [];
EventMgr.add(window, "_unload", this.cleanup);
}
},
add:function(o, t, fn, uc) {
this.initialize();
if(typeof o == "string")
o = document.getElementById(o);
if(o == null || fn == null)
return false;
if(t == "unload") {
// call later when cleanup is called. don't hook up
this._registry.push({obj:o, type:t, fn:fn, useCapture:uc});
return true;
}
var realType = t=="_unload"?"unload":t;
o.addEventListener(realType, fn, uc);
this._registry.push({obj:o, type:t, fn:fn, useCapture:uc});
return true;
},
cleanup:function() {
for(var i = 0; i < EventMgr._registry.length; i++)
with(EventMgr._registry[i])
if(type=="unload")
fn();
else {
if(type == "_unload") type = "unload";
obj.removeEventListener(type,fn,useCapture);
}
EventMgr._registry = null;
}
};
Usage is simple: where you previously wrote
node.addEventListener( "click", handler, false ) instead write EventMgr.add( node, "click", handler, false ) -- in other words, it's just moving the node to the head of the list of parameters and substituting addEventListener for EventMgr.add.The class assumes a DOM compliant browser (so it's not IE compatible, for instance), but I have had very good use for it in my user scripts, where the code gets to run on mostly any page I visit, across the entire web -- which can add up to lots of leakage in the long run, if you write sloppy code. But any event handler you add using the above method also gets removed as you leave the page without your lifting a finger.
Even before elder mozillan wizards squash the bugs deep down near the firefox core.
Categories:
2006-05-02
Mine. And yours, too!
All of the code examples, javascript snippets, user scripts, utilities, blog template add-ons and so on I write and post about here are put in the public domain, unless otherwise mentioned, or bound by related lifted-in code with viral licenses. It is my gift back to the online community, encouraging others to join, pick up ideas or good practices, and hopefully share their own ideas and findings, too. Especially including picking up on ideas I strew about, building Something Real on top of them. After all, the value of an idea is close to zero on its own, but follow it through, build and maintain it well, and its value skyrockets.
A free exchange of ideas, knowledge, experiences, practices and tools is what makes the web this great environment to work in, and with, and I want to do my part in fostering that spirit. Occasionally lifting DRY (Don't Repeat Yourself) to Don't Repeat Others Either, when possible; my own time spent at writing something really good, evaluating or researching something, would ideally not be useful to myself alone, but to you too.
Licenses make that more bothersome. A Creative Commons license, while nice in spirit and generally about sharing, still brings law to code, and even if that is just about proper attribution, it raises barriers. Where would you have to show what author how, in the context of your derived work? What constitutes a derived work, in terms of code? And so on, in endless cascade. This code is mine, and it is yours, and we may all do what we like with it. Credit me if and however you feel appropriate and I will be glad, or do not, and I will respect that too. I encourage you to keep docs and pointers around, following and spreading healthy practices, sharing and contributing, but will not force you to do either by power of law. I will never write Greasemonkey scripts that are more license text than code, but feel a bit sorry for those who do.
Share and enjoy!
A free exchange of ideas, knowledge, experiences, practices and tools is what makes the web this great environment to work in, and with, and I want to do my part in fostering that spirit. Occasionally lifting DRY (Don't Repeat Yourself) to Don't Repeat Others Either, when possible; my own time spent at writing something really good, evaluating or researching something, would ideally not be useful to myself alone, but to you too.
Licenses make that more bothersome. A Creative Commons license, while nice in spirit and generally about sharing, still brings law to code, and even if that is just about proper attribution, it raises barriers. Where would you have to show what author how, in the context of your derived work? What constitutes a derived work, in terms of code? And so on, in endless cascade. This code is mine, and it is yours, and we may all do what we like with it. Credit me if and however you feel appropriate and I will be glad, or do not, and I will respect that too. I encourage you to keep docs and pointers around, following and spreading healthy practices, sharing and contributing, but will not force you to do either by power of law. I will never write Greasemonkey scripts that are more license text than code, but feel a bit sorry for those who do.
Share and enjoy!
Categories:
Subscribe to:
Comments (Atom)