Leak Free Event Observation Patch for Prototype

2006-10-24 +8 Update: According to IE 7 vs IE 6, IE 7 seems to have solved the memory leaks. So this patch is not needed for IE7.

2006-09-05 15:33:39 GMT+0800 UPDATE: I found that this patch breaks Event.stopObserving, I’ll update it ASAP.

Here is a Prototype patch addressing the IE memory leak problem with closures. With this patch applied, we can use nested functions as event handlers without leaking memory in IE.

Fixes and features:

  • Fix IE memory leak when bound nested functions are used as event handlers. bind() and bindAsEventListener() now use leak free closure
  • Fix IE memory leak when an unbound function is passed to Event.observe()
  • In IE, this pointer now points to the element being ebserved inside an unbound observer(this use to always point to the window object in IE)
  • Mixed Ross’s fast load solution in. Observers to window’s load event are triggered right after the document finishes loading

e.g.

function init() {
    new Insertion.Bottom(document.body, '<span id="mySpan">Leak free</span>');
    var span = $('mySpan');
    //does not leak any more
    span.onclick = function(evt) {alert(this.innerHTML);}.bindAsEventListener(span);
    //does not leak any more
    var mouseoverHandler = function() {
         //this will point to span
        $(this.setStyle({backgroudColor: 'green'});
    };
    Event.observe(span, 'mouseover', mouseoverHandler);
}

Patch(make sure code below is executed after code in prototype.js):

//Leak free event observation patch for Prototype
//Written by Arrix, 2006-08-24 17:15:55 GMT+0800
//with input from Ross and Laurens
//
//Fixes and features:
//* Fix IE memory leak when bound nested functions are used as event handlers. bind() and bindAsEventListener() now use leak free closure
//* Fix IE memory leak when an unbound function is passed to Event.observe()
//* In IE, this pointer now points to the element being ebserved inside an unbound observer(this use to always point to the window object in IE)
//* Mixed Ross's fast load solution in. Observers to window's load event are triggered right after the document finishes loading
//http://www.agileweb.org/articles/2006/06/26/speeding-up-onload-update
//http://www.agileweb.org/articles/2006/07/28/onload-final-update
//http://laurens.vd.oever.nl/weblog/items2005/closures/
Object.extend(Event, {
    _observeAndCache: function(element, name, observer, useCapture) {
        if (!this.observers) this.observers = [];
        var i = Event.observers.length;
        //CAUTION: DO NOT bind window as this pointer in IE
        //this pointer inside an event handler always points to the window object if the event handler is attached using IE's attachEvent() function
        var wrapper = function() {var thisObj = this === window && navigator.appVersion.match(/\bMSIE\b/) ? null : this; Event.observers[i][2].apply(thisObj || Event.observers[i][0], arguments);};
        if (element.addEventListener) {
         this.observers.push([element, name, observer, useCapture]);
         element.addEventListener(name, wrapper, useCapture);
        } else if (element.attachEvent) {
         this.observers.push([element, name, observer, useCapture]);
         element.attachEvent('on' + name, wrapper);
        }
        element = observer = wrapper = null;
    },
    
    observe: function(element, name, observer, useCapture) {
        element = $(element);
        useCapture = useCapture || false;
        
        if (name == 'keypress' &&
            (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
            || element.attachEvent))
         name = 'keydown';
        
        if (name == 'load' && element.screen) {
         this._observeLoad(element, name, observer, useCapture);
         return;
    }
    //Assuming that browsers which support DOM2 event model do not have the memory leak problem, we don't need to _observeAndCache()
    if
        element.addEventListener(name, observer, useCapture);
        return;
    }
    
    Event._observeAndCache(element, name, observer, useCapture);
    },
    _observeLoad : function(element, name, observer, useCapture) {
        if (!this._readyCallbacks) {
         var loader = this._onloadWindow.bind(this);
         if (document.addEventListener)
             document.addEventListener("DOMContentLoaded", loader, false);
         //conditional comment will be stripped by custom_rhino, we use browser detection instead
    //     /*@cc_on @*/
    //     /*@if (@_win32)
    //         if (! $("__ie_onload")) {
    //            document.write("<script id='__ie_onload' defer='true' src='://'><\/script>");
    //            var script = $("__ie_onload");
    //            script.onreadystatechange = function() { if (this.readyState == "complete") loader(); };
    //        } else {
    //            loader();
    //        }
    //     /*@end @*/
         if (navigator.appVersion.match(/\bMSIE\b/)) {
            if (! $("__ie_onload")) {
                document.write("<script id='__ie_onload' defer='true' src='://'><\/script>");
                var script = $("__ie_onload");
                script.onreadystatechange = function() { if (this.readyState == "complete") loader(); };
            } else {
                loader();
            }
         }
         if (navigator.appVersion.match(/Konqueror|Safari|KHTML/i))
            Event._timer = setInterval(function() {if (/loaded|complete/.test(document.readyState))loader();}, 10);
         Event._readyCallbacks = [];
         this._observeAndCache(element, name, loader, useCapture);
        }
        Event._readyCallbacks.push(observer);
    },
    _onloadWindow : function() {
        if (arguments.callee.done) return;
        arguments.callee.done = true;
        if (this._timer) clearInterval(this._timer);
        this._readyCallbacks.each(function(f) { f() });
        this._readyCallbacks = null;
    }
});
//Leak free bind
Function.prototype.bind = function() {
    var __method = this, args = $A(arguments), object = args.shift();
    return function() {
    return __method.apply(object, args.concat($A(arguments)));
    }.zm_closure();
};
Function.prototype.bindAsEventListener = function(object) {
    var __method = this, args = $A(arguments), object = args.shift();
    return function(event) {
    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
    }.zm_closure();
};
//zm_ is simply a prefix used in my project to avoid naming conflicts
Function.prototype.zm_closure = function()
{
    if (!window.__funs) window.__funs = [];
    var fun = this;
    var funId = this.__funId;
    if (!funId) __funs[funId = fun.__funId = __funs.length] = fun;
    fun = null;
    return function ()
    {
    return __funs[funId].apply(null, arguments);
    };
};
This entry was posted in JavaScript. Bookmark the permalink.

25 Responses to Leak Free Event Observation Patch for Prototype

  1. Unknown says:

    wow gold!All wow gold US Server 24.99$/1000G on sell! Cheap wow gold,wow gold,wow gold,Buy Cheapest/Safe/Fast WoW US EU wow gold Power leveling wow gold from the time you wWorld of Warcraft gold ordered!

    wow power leveling wow power leveling power leveling wow power leveling wow powerleveling wow power levelingcheap wow power leveling wow power leveling buy wow power leveling wow power leveling buy power leveling wow power leveling cheap power leveling wow power leveling wow power leveling wow power leveling wow powerleveling wow power leveling power leveling wow power leveling wow powerleveling wow power leveling buy rolex cheap rolex wow gold wow gold wow gold wow gold -210090677514642

  2. Unknown says:

    不動産投資 システム開発 札幌 不動産 仙台 不動産 大阪 不動産 横浜 不動産 名古屋 不動産 福岡 不動産 京都 不動産 埼玉 不動産 千葉 不動産 静岡 不動産 神戸 不動産 浜松 不動産 堺市 不動産 川崎市 不動産 相模原市 不動産 姫路 不動産 岡山 不動産 明石 不動産 鹿児島 不動産 北九州市 不動産 熊本 不動産 インテリアコーディネータ リフォーム 東京 リフォーム 大阪 不動産 査定 不動産 買取 不動産 売買 不動産 鑑定 不動産 売却 サイトを検索すると会社があったよくみると賃貸 住宅も収益物件も不動産 賃貸も賃貸マンションも新築マンションもしっかりカバーしてありすごく充実したさいとでもちろん投資を目的の方やリフォームをしたい人もすごく参考になるだう。ところで今、SEO対策などいまはやっているがホームページ制作会社にいらいしてもうまくはいかないようだ。最近私は、資産運用にこっていて税金対策にインテリアを集めている。もちろんファッションにこだわりブランド品や下着にはこだわりがある。 化粧品も高価なものがよく家具も最高級しか買わない、先日海外旅行にいってきてお土産に外車と結婚指輪と高級時計をかったが、日本でしらべたら通販ですごく安く売っていた。
    今、会社の寮で賃貸を探してまして全部で12都市で社員が住みます場所は、福岡 賃貸,広島 賃貸,川崎 賃貸,神戸 賃貸,京都 賃貸,名古屋 賃貸,大阪 賃貸,埼玉 賃貸,札幌 賃貸,仙台 賃貸,千葉 賃貸,横浜 賃貸の政令指定都市が対象です不動産と賃貸と投資とは収益物件探し新築の住宅はアパートとマンションの土地から不動産投資

  3. Unknown says:


    信是個富有挑戰的工作,忙碌、刺激、激情。最后的結局總是有人哭,有人笑。在徵信社工作的幾年時間里,我感悟到很多生活的無奈與殘酷。閑暇時我去中古车市
    场,感覺工作太緊張,放松一下而已,不是純粹的為了淘二手车。私家偵探也就是徵信工作人員似乎是個很酷的詞,但是如果誰需要私家偵探來幫忙的話,他(她)
    的婚姻也許已經亮起了紅燈。每天陪著星際客戶喝著咖啡,似乎是一件很爽的事,可是她們的眼淚比咖啡要苦的多。常常聽他們說嘈雜的燈光音響麻痹著他們的神
    經,讓他們過著醉生夢死的生活。其實,誰不渴望幸福美滿的愛情。沒有團體制服不了那些玩弄生活、玩弄感情的人,于是,徵信社應運而生。這不知道是人們的福
    音還是不幸,希望天下的每一個人都歡樂著、幸福著。坐月子是女人一生的大事,女人可以为了襁褓中的婴儿放弃一直引用的红酒而吃月子餐,这时候的女人是幸福
    而伟大的。有人歡喜有人優,有人狂笑有人大哭,我不想看到女人太多的眼淚,辭職后,我做了一位安靜、平和的室內設計師。虽然上下班没有了车接车送,但我租
    车怡然自得。偶爾和Fake
    Rolex Watch, Breitling
    Replica Watch, Best
    replica watches, Omega
    Replica Watches ecosway的朋友小聚,很愜意

  4. Unknown says:

    Hi,Do you have used LCDs, used flat screens and secondhand LCDs? Please go here:www.sstar-hk.com(Southern Stars).We are constantly buying re-usable LCD panels and working for LCD recycling.The re-usable panels go through strictly designed process of categorizing, checking, testing, repairing and refurbishing before they are re-used to make remanufactured LCD displays and TV sets.Due to our recent breakthrough in testing and repairing technology of LCD, we can improve the value for your LCD panels.
    Contact Us
    E-mail:sstar@netvigator.com
    website:www.sstar-hk.com

  5. Unknown says:

    外壁,防水,屋根,塗装専門店,ペイント,塗料,ペンキ,カラモニー塗り替え,塗り替え金額,塗り替え期間、塗り替え仕上,塗替え,外壁塗装,リフォーム,塗装,塗装業者,住宅塗装,塗料,日本ペイント, 外壁塗装を考えている方は必見です 。アクサダイレクト東京/大阪のクリエイター育成専門の学校 バンタンデザイン研究所。大阪 専門学校ファッションや美容の専門の学校です. 大阪 専門学校デザインスクール最大級の超複合型イベント。

  6. Unknown says:

    株式投資 テレマーケティング  出産祝い 会社設立 ショッピング枠 現金化  フレッツ 
    お見合いパーティー  RAID復旧  看護師  オーク  RMT  Bフレッツ  育毛剤  自動車保険 比較 
    アルカリイオン水

  7. Unknown says:

    お取り寄せグルメ  東京 ホームページ制作 カーボンオフセット  鼻づまり  いびき   腰痛  フレッツ 光  データ復元  自動車保険  釣り  データ復旧  結婚指輪  CAD  マンション フロント  toefl 

  8. Unknown says:

    ありがとうございました

  9. Unknown says:

    http://www.bestcooldesigner.com/nhljerseysmensbuffalosabres-c-1_12.html Buffalo Sabres Jerseyshttp://www.bestcooldesigner.com/nhljerseysmensbuffalosabres-c-1_12.html Buffalo Sabres Jersey

Leave a comment