PDA

View Full Version : [2.1/2.2] Array.remove in IE7 doesn't work with TaskMgr.



janus03
15 Aug 2008, 1:40 AM
To reproduce:

var task = {
run: function() {
console.log("run"); // whatever you need to see that the task runs repeatedly in IE7
Ext.TaskMgr.stop(task);
},
interval: 1000
}
task = Ext.TaskMgr.start(task);

The task is never stopped in IE7 because the Array.remove method doesn't remove the task from the tasks array in Ext.util.TaskRunner.stop.

HtmlEditor suffers greatly under this bug when placed in a TabPanel in a Window when the Window is destroyed.

Fix: Always use the Array.remove implementation in Ext when IE7 is detected (in Ext.js).

Ext versions tested: 2.1 and 2.2
Browsers tested:

IE7/Windows
Firefox3/Windows (working)


Edit: changed document.write to console.log (unrelated to bug)

Condor
15 Aug 2008, 2:59 AM
Can you actually call document.write() after the document has finished loading?

This doesn't have any problems in IE7 and FF3:


Ext.onReady(function(){
var cfg = {
run: function(i) {
Ext.DomHelper.append(Ext.getBody(), 'run<br/>');
Ext.TaskMgr.stop(task); // or simply: return false;
},
interval: 1000
}
task = Ext.TaskMgr.start(cfg);
});

janus03
15 Aug 2008, 3:08 AM
The code above is a rough copy of HtmlEditor.initEditor - and it uses Ext.TaskMgr.stop to stop the task (which doesn't work).

Condor
15 Aug 2008, 3:27 AM
Yes, that's a bug!

It references the task variable in a scope in which it isn't available.

Fix:


Ext.override(Ext.form.HtmlEditor, {
initFrame : function(){
this.doc = this.getDoc();
this.win = this.getWin();
this.doc.open();
this.doc.write(this.getDocMarkup());
this.doc.close();
var task = {
run : function(){
if(this.doc.body || this.doc.readyState == 'complete'){
//Ext.TaskMgr.stop(task);
this.doc.designMode="on";
this.initEditor.defer(10, this);
return false;
}
},
interval : 10,
duration:10000,
scope: this
};
Ext.TaskMgr.start(task);
}
});

janus03
15 Aug 2008, 3:30 AM
Funny thing is - it works in Firefox3.

janus03
15 Aug 2008, 3:33 AM
And - it actually passes the task object in IE correctly (just stepped through it). Problem is that the tasks.remove in TaskRunner.runTasks doesn't remove it properly from the tasks array.

Condor
15 Aug 2008, 3:46 AM
It references the task variable in a scope in which it isn't available.

Hmm.. No that can't be the problem... But this change certainly makes things better.

Condor
15 Aug 2008, 4:05 AM
While looking at Ext.util.TaskRunner I noticed the following error:


var runTasks = function(){
if(removeQueue.length > 0){
for(var i = 0, len = removeQueue.length; i < len; i++){
tasks.remove(removeQueue[i]);
}
removeQueue = [];
if(tasks.length < 1){
stopThread();
return;
}
}
var now = new Date().getTime();
for(var i = 0, len = tasks.length; i < len; ++i){
var t = tasks[i];
var itime = now - t.taskRunTime;
if(t.interval <= itime){
var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
t.taskRunTime = now;
if(rt === false || t.taskRunCount === t.repeat){
removeTask(t);
//return;
continue;
}
}
if(t.duration && t.duration <= (now - t.taskStartTime)){
removeTask(t);
}
}
};

(has nothing to do with the bugreport, but it should be fixed)

janus03
15 Aug 2008, 4:34 AM
Ext assumes that Array.remove(e) works by removing e from Array in IE7 -- but IE7 has a different implementation of Array.remove. Since Ext only uses it's own implementation of Array.remove if it isn't already implemented we run into the following:

var task = {
test: "test string"
}
var a = [task];
a.remove(task);
console.log(a);

// logs [ Object test="test string" ] in IE -- but Ext classes (TaskRunner fx) expects it to be [].


Hope this makes it clearer.

Condor
15 Aug 2008, 5:49 AM
I tested your example, but it behaves correctly on my IE7 and FF3.

ps. IE7 doesn't have native support for Array.remove(item).
Both IE7 and FF3 will use the override from Ext (using this.splice(this.indexOf(item), 1)).