Removed try/catch/finally and idleWorkTimer

BUG: sometimes cursor gets hidden, can't type anymore.
This commit is contained in:
Hans Pinckaers 2011-08-25 15:57:08 +02:00
parent 66e616304d
commit ded9825097
2 changed files with 314 additions and 605 deletions

View file

@ -24,7 +24,7 @@ hash node > /dev/null 2>&1 || {
NODE_VERSION=$(node --version) NODE_VERSION=$(node --version)
if [ ! $(echo $NODE_VERSION | cut -d "." -f 1-2) = "v0.4" ]; then if [ ! $(echo $NODE_VERSION | cut -d "." -f 1-2) = "v0.4" ]; then
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.4.x" >&2 echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.4.x" >&2
exit 1 # exit 1
fi fi
#Is npm installed? #Is npm installed?

View file

@ -306,9 +306,25 @@ function OUTER(gscope)
if (currentCallStack) if (currentCallStack)
{ {
console.error("Can't enter callstack " + type + ", already in " + currentCallStack.type); window.console.log("Can't enter callstack " + type + ", already in " + currentCallStack.type);
return;
} }
currentCallStack = {
type: type,
docTextChanged: false,
selectionAffected: false,
userChangedSelection: false,
domClean: false,
profileRest: profileRest,
isUserChange: false,
// is this a "user change" type of call-stack
repChanged: false,
editEvent: newEditEvent(type),
startNewEvent: startNewEvent
};
var profiling = false; var profiling = false;
function profileRest() function profileRest()
@ -378,41 +394,17 @@ function OUTER(gscope)
return oldEvent; return oldEvent;
} }
currentCallStack = {
type: type,
docTextChanged: false,
selectionAffected: false,
userChangedSelection: false,
domClean: false,
profileRest: profileRest,
isUserChange: false,
// is this a "user change" type of call-stack
repChanged: false,
editEvent: newEditEvent(type),
startNewEvent: startNewEvent
};
var cleanExit = false; var cleanExit = false;
var result; var result;
try
{
result = action();
//console.log("Just did action for: "+type);
cleanExit = true;
}
catch (e)
{
caughtErrors.push(
{
error: e,
time: +new Date()
});
dmesg(e.toString());
throw e;
}
finally
{
var cs = currentCallStack; var cs = currentCallStack;
//console.log("Finished action for: "+type);
// window.console.log("doing action: "+action);
result = action();
cleanExit = true;
if (cleanExit) if (cleanExit)
{ {
submitOldEvent(cs.editEvent); submitOldEvent(cs.editEvent);
@ -427,6 +419,7 @@ function OUTER(gscope)
if (cs.selectionAffected && !(browser.safari && (type == "applyChangesToBase" || type == "idleWorkTimer"))) if (cs.selectionAffected && !(browser.safari && (type == "applyChangesToBase" || type == "idleWorkTimer")))
{ {
updateBrowserSelectionFromRep(); updateBrowserSelectionFromRep();
updateLineNumbers();
} }
if ((cs.docTextChanged || cs.userChangedSelection) && cs.type != "applyChangesToBase") if ((cs.docTextChanged || cs.userChangedSelection) && cs.type != "applyChangesToBase")
{ {
@ -443,12 +436,17 @@ function OUTER(gscope)
// non-clean exit // non-clean exit
if (currentCallStack.type == "idleWorkTimer") if (currentCallStack.type == "idleWorkTimer")
{ {
window.console.log("set idle work timer");
idleWorkTimer.atLeast(1000); idleWorkTimer.atLeast(1000);
} }
} }
currentCallStack = null; currentCallStack = null;
if (profiling) console.profileEnd(); if (profiling) console.profileEnd();
}
//}, 0);
return result; return result;
} }
editorInfo.ace_inCallStack = inCallStack; editorInfo.ace_inCallStack = inCallStack;
@ -916,6 +914,7 @@ function OUTER(gscope)
performSelectionChange([0, rep.lines.atIndex(0).lineMarker], [0, rep.lines.atIndex(0).lineMarker]); performSelectionChange([0, rep.lines.atIndex(0).lineMarker], [0, rep.lines.atIndex(0).lineMarker]);
window.console.log("set idle work timer");
idleWorkTimer.atMost(100); idleWorkTimer.atMost(100);
if (rep.alltext != atext.text) if (rep.alltext != atext.text)
@ -1340,56 +1339,60 @@ function OUTER(gscope)
return; return;
} }
inCallStack("idleWorkTimer", function() // inCallStack("idleWorkTimer", function()
{ // {
var isTimeUp = newTimeLimit(250); // var isTimeUp = newTimeLimit(250);
//console.time("idlework"); // //console.time("idlework");
var finishedImportantWork = false; // var finishedImportantWork = false;
var finishedWork = false; // var finishedWork = false;
try // try
{ // {
// isTimeUp() is a soft constraint for incorporateUserChanges, // // isTimeUp() is a soft constraint for incorporateUserChanges,
// which always renormalizes the DOM, no matter how long it takes, // // which always renormalizes the DOM, no matter how long it takes,
// but doesn't necessarily lex and highlight it // // but doesn't necessarily lex and highlight it
incorporateUserChanges(isTimeUp); // incorporateUserChanges(isTimeUp);
if (isTimeUp()) return; // if (isTimeUp()) return;
updateLineNumbers(); // update line numbers if any time left // updateLineNumbers(); // update line numbers if any time left
if (isTimeUp()) return; // if (isTimeUp()) return;
var visibleRange = getVisibleCharRange(); // var visibleRange = getVisibleCharRange();
var docRange = [0, rep.lines.totalWidth()]; // var docRange = [0, rep.lines.totalWidth()];
//console.log("%o %o", docRange, visibleRange); // //console.log("%o %o", docRange, visibleRange);
finishedImportantWork = true; // finishedImportantWork = true;
finishedWork = true; // finishedWork = true;
} // }
finally // finally
{ // {
//console.timeEnd("idlework"); // //console.timeEnd("idlework");
if (finishedWork) // if (finishedWork)
{ // {
idleWorkTimer.atMost(1000); // // window.console.log("set idle work timer");
} // // COMMENTED OUT!
else if (finishedImportantWork) // // idleWorkTimer.atMost(1000);
{ // }
// if we've finished highlighting the view area, // else if (finishedImportantWork)
// more highlighting could be counter-productive, // {
// e.g. if the user just opened a triple-quote and will soon close it. // // if we've finished highlighting the view area,
idleWorkTimer.atMost(500); // // more highlighting could be counter-productive,
} // // e.g. if the user just opened a triple-quote and will soon close it.
else // window.console.log("set idle work timer");
{ // idleWorkTimer.atMost(500);
var timeToWait = Math.round(isTimeUp.elapsed() / 2); // }
if (timeToWait < 100) timeToWait = 100; // else
idleWorkTimer.atMost(timeToWait); // {
} // window.console.log("set idle work timer");
} // var timeToWait = Math.round(isTimeUp.elapsed() / 2);
}); // if (timeToWait < 100) timeToWait = 100;
// idleWorkTimer.atMost(timeToWait);
// }
// }
// });
//if (! top.AFTER) top.AFTER = []; //if (! top.AFTER) top.AFTER = [];
//top.AFTER.push(magicdom.root.dom.innerHTML); //top.AFTER.push(magicdom.root.dom.innerHTML);
@ -1753,6 +1756,8 @@ function OUTER(gscope)
if (browser.msie) if (browser.msie)
{ {
// try to undo IE's pesky and overzealous linkification // try to undo IE's pesky and overzealous linkification
window.console.log("try here!");
try try
{ {
n.createTextRange().execCommand("unlink", false, null); n.createTextRange().execCommand("unlink", false, null);
@ -1983,10 +1988,12 @@ function OUTER(gscope)
else p2.literal(0, "nonopt"); else p2.literal(0, "nonopt");
lastEntry = entry; lastEntry = entry;
p2.mark("spans"); p2.mark("spans");
getSpansForLine(entry, function(tokenText, tokenClass) getSpansForLine(entry, function(tokenText, tokenClass)
{ {
info.appendSpan(tokenText, tokenClass); info.appendSpan(tokenText, tokenClass);
}, lineStartOffset, isTimeUp()); }, lineStartOffset, isTimeUp());
//else if (entry.text.length > 0) { //else if (entry.text.length > 0) {
//info.appendSpan(entry.text, 'dirty'); //info.appendSpan(entry.text, 'dirty');
//} //}
@ -3103,7 +3110,9 @@ function OUTER(gscope)
// an object property doesn't // an object property doesn't
setAssoc(lineElem, "unpasted", {}); setAssoc(lineElem, "unpasted", {});
}; };
var lineClass = 'ace-line'; var lineClass = 'ace-line';
result.appendSpan = function(txt, cls) result.appendSpan = function(txt, cls)
{ {
if ((!txt) && cls) if ((!txt) && cls)
@ -3111,7 +3120,7 @@ function OUTER(gscope)
// gain a whole-line style (currently to show insertion point in CSS) // gain a whole-line style (currently to show insertion point in CSS)
lineClass = domline.addToLineClass(lineClass, cls); lineClass = domline.addToLineClass(lineClass, cls);
} }
// otherwise, ignore appendSpan, this is an empty line // // otherwise, ignore appendSpan, this is an empty line
}; };
result.clearSpans = function() result.clearSpans = function()
{ {
@ -3475,7 +3484,7 @@ function OUTER(gscope)
inCallStack("handleClick", function() inCallStack("handleClick", function()
{ {
idleWorkTimer.atMost(200); // idleWorkTimer.atMost(200);
}); });
// only want to catch left-click // only want to catch left-click
@ -3495,6 +3504,8 @@ function OUTER(gscope)
} }
if (n && isLink(n)) if (n && isLink(n))
{ {
window.console.log("try here!");
try try
{ {
var newWindow = window.open(n.href, '_blank'); var newWindow = window.open(n.href, '_blank');
@ -3739,7 +3750,6 @@ function OUTER(gscope)
function handleKeyEvent(evt) function handleKeyEvent(evt)
{ {
// if (DEBUG && window.DONT_INCORP) return;
if (!isEditable) return; if (!isEditable) return;
var type = evt.type; var type = evt.type;
@ -3747,7 +3757,10 @@ function OUTER(gscope)
var keyCode = evt.keyCode; var keyCode = evt.keyCode;
var which = evt.which; var which = evt.which;
//dmesg("keyevent type: "+type+", which: "+which); // TEST FOR KEYBOARD RESPONSE IPAD
//setTimeout(function(){
// if (DEBUG && window.DONT_INCORP) return;
// Don't take action based on modifier keys going up and down. // Don't take action based on modifier keys going up and down.
// Modifier keys do not generate "keypress" events. // Modifier keys do not generate "keypress" events.
// 224 is the command-key under Mac Firefox. // 224 is the command-key under Mac Firefox.
@ -3893,12 +3906,14 @@ function OUTER(gscope)
} }
else else
{ {
idleWorkTimer.atLeast(500); // window.console.log("set idle work timer");
// idleWorkTimer.atLeast(500);
} }
} }
else if (type == "keyup") else if (type == "keyup")
{ {
var wait = 200; var wait = 200;
// window.console.log("set idle work timer");
idleWorkTimer.atLeast(wait); idleWorkTimer.atLeast(wait);
idleWorkTimer.atMost(wait); idleWorkTimer.atMost(wait);
} }
@ -3929,6 +3944,8 @@ function OUTER(gscope)
thisKeyDoesntTriggerNormalize = false; thisKeyDoesntTriggerNormalize = false;
} }
}); });
// }, 10); //setTimeout (performance??);
} }
var thisKeyDoesntTriggerNormalize = false; var thisKeyDoesntTriggerNormalize = false;
@ -4024,6 +4041,9 @@ function OUTER(gscope)
function hasIESelection() function hasIESelection()
{ {
var browserSelection; var browserSelection;
window.console.log("try here!");
try try
{ {
browserSelection = doc.selection; browserSelection = doc.selection;
@ -4053,6 +4073,9 @@ function OUTER(gscope)
if (browser.msie) if (browser.msie)
{ {
var browserSelection; var browserSelection;
window.console.log("try here!");
try try
{ {
browserSelection = doc.selection; browserSelection = doc.selection;
@ -4386,10 +4409,10 @@ function OUTER(gscope)
moveToElementText(s, n); moveToElementText(s, n);
// work around for issue that caret at beginning of line // work around for issue that caret at beginning of line
// somehow ends up at end of previous line // somehow ends up at end of previous line
if (s.move('character', 1)) // if (s.move('character', 1))
{ // {
s.move('character', -1); // s.move('character', -1);
} // }
s.collapse(true); // to start s.collapse(true); // to start
} }
} }
@ -4749,8 +4772,11 @@ function OUTER(gscope)
function setDesignMode(newVal) function setDesignMode(newVal)
{ {
try
{ // window.console.log("try here!");
// try
// {
function setIfNecessary(target, prop, val) function setIfNecessary(target, prop, val)
{ {
if (String(target[prop]).toLowerCase() != val) if (String(target[prop]).toLowerCase() != val)
@ -4774,11 +4800,11 @@ function OUTER(gscope)
} }
} }
return true; return true;
} // }
catch (e) // catch (e)
{ // {
return false; // return false;
} // }
} }
var iePastedLines = null; var iePastedLines = null;
@ -4824,10 +4850,16 @@ function OUTER(gscope)
function bindTheEventHandlers() function bindTheEventHandlers()
{ {
bindEventHandler(window, "unload", teardown); bindEventHandler(window, "unload", teardown);
bindEventHandler(document, "keydown", handleKeyEvent); // bindEventHandler(document, "keydown", handleKeyEvent);
bindEventHandler(document, "keypress", handleKeyEvent); // bindEventHandler(document, "keypress", handleKeyEvent);
// added
bindEventHandler(document, "paste", handleKeyEvent);
bindEventHandler(document, "cut", handleKeyEvent);
bindEventHandler(document, "keyup", handleKeyEvent); bindEventHandler(document, "keyup", handleKeyEvent);
bindEventHandler(document, "click", handleClick); bindEventHandler(document, "click", handleClick);
bindEventHandler(root, "blur", handleBlur); bindEventHandler(root, "blur", handleBlur);
if (browser.msie) if (browser.msie)
{ {
@ -4936,6 +4968,8 @@ function OUTER(gscope)
if (browser.msie) if (browser.msie)
{ {
// cache CSS background images // cache CSS background images
window.console.log("try here!");
try try
{ {
doc.execCommand("BackgroundImageCache", false, true); doc.execCommand("BackgroundImageCache", false, true);
@ -5248,335 +5282,10 @@ function OUTER(gscope)
} }
editorInfo.ace_doInsertUnorderedList = doInsertUnorderedList; editorInfo.ace_doInsertUnorderedList = doInsertUnorderedList;
var mozillaFakeArrows = (browser.mozilla && (function() var mozillaFakeArrows = "";
{
// In Firefox 2, arrow keys are unstable while DOM-manipulating
// operations are going on. Specifically, if an operation
// (computation that ties up the event queue) is going on (in the
// call-stack of some event, like a timeout) that at some point
// mutates nodes involved in the selection, then the arrow
// keypress may (randomly) move the caret to the beginning or end
// of the document. If the operation also mutates the selection
// range, the old selection or the new selection may be used, or
// neither.
// As long as the arrow is pressed during the busy operation, it
// doesn't seem to matter that the keydown and keypress events
// aren't generated until afterwards, or that the arrow movement
// can still be stopped (meaning it hasn't been performed yet);
// Firefox must be preserving some old information about the
// selection or the DOM from when the key was initially pressed.
// However, it also doesn't seem to matter when the key was
// actually pressed relative to the time of the mutation within
// the prolonged operation. Also, even in very controlled tests
// (like a mutation followed by a long period of busyWaiting), the
// problem shows up often but not every time, with no discernable
// pattern. Who knows, it could have something to do with the
// caret-blinking timer, or DOM changes not being applied
// immediately.
// This problem, mercifully, does not show up at all in IE or
// Safari. My solution is to have my own, full-featured arrow-key
// implementation for Firefox.
// Note that the problem addressed here is potentially very subtle,
// especially if the operation is quick and is timed to usually happen
// when the user is idle.
// features:
// - 'up' and 'down' arrows preserve column when passing through shorter lines
// - shift-arrows extend the "focus" point, which may be start or end of range
// - the focus point is kept horizontally and vertically scrolled into view
// - arrows without shift cause caret to move to beginning or end of selection (left,right)
// or move focus point up or down a line (up,down)
// - command-(left,right,up,down) on Mac acts like (line-start, line-end, doc-start, doc-end)
// - takes wrapping into account when doesWrap is true, i.e. up-arrow and down-arrow move
// between the virtual lines within a wrapped line; this was difficult, and unfortunately
// requires mutating the DOM to get the necessary information
var savedFocusColumn = 0; // a value of 0 has no effect
var updatingSelectionNow = false;
function getVirtualLineView(lineNum)
{
var lineNode = rep.lines.atIndex(lineNum).lineNode;
while (lineNode.firstChild && isBlockElement(lineNode.firstChild))
{
lineNode = lineNode.firstChild;
}
return makeVirtualLineView(lineNode);
}
function markerlessLineAndChar(line, chr)
{
return [line, chr - rep.lines.atIndex(line).lineMarker];
}
function markerfulLineAndChar(line, chr)
{
return [line, chr + rep.lines.atIndex(line).lineMarker];
}
return {
notifySelectionChanged: function()
{
if (!updatingSelectionNow)
{
savedFocusColumn = 0;
}
},
handleKeyEvent: function(evt)
{
// returns "true" if handled
if (evt.type != "keypress") return false;
var keyCode = evt.keyCode;
if (keyCode < 37 || keyCode > 40) return false;
incorporateUserChanges();
if (!(rep.selStart && rep.selEnd)) return true;
// {byWord,toEnd,normal}
var moveMode = (evt.altKey ? "byWord" : (evt.ctrlKey ? "byWord" : (evt.metaKey ? "toEnd" : "normal")));
var anchorCaret = markerlessLineAndChar(rep.selStart[0], rep.selStart[1]);
var focusCaret = markerlessLineAndChar(rep.selEnd[0], rep.selEnd[1]);
var wasCaret = isCaret();
if (rep.selFocusAtStart)
{
var tmp = anchorCaret;
anchorCaret = focusCaret;
focusCaret = tmp;
}
var K_UP = 38,
K_DOWN = 40,
K_LEFT = 37,
K_RIGHT = 39;
var dontMove = false;
if (wasCaret && !evt.shiftKey)
{
// collapse, will mutate both together
anchorCaret = focusCaret;
}
else if ((!wasCaret) && (!evt.shiftKey))
{
if (keyCode == K_LEFT)
{
// place caret at beginning
if (rep.selFocusAtStart) anchorCaret = focusCaret;
else focusCaret = anchorCaret;
if (moveMode == "normal") dontMove = true;
}
else if (keyCode == K_RIGHT)
{
// place caret at end
if (rep.selFocusAtStart) focusCaret = anchorCaret;
else anchorCaret = focusCaret;
if (moveMode == "normal") dontMove = true;
}
else
{
// collapse, will mutate both together
anchorCaret = focusCaret;
}
}
if (!dontMove)
{
function lineLength(i)
{
var entry = rep.lines.atIndex(i);
return entry.text.length - entry.lineMarker;
}
function lineText(i)
{
var entry = rep.lines.atIndex(i);
return entry.text.substring(entry.lineMarker);
}
if (keyCode == K_UP || keyCode == K_DOWN)
{
var up = (keyCode == K_UP);
var canChangeLines = ((up && focusCaret[0]) || ((!up) && focusCaret[0] < rep.lines.length() - 1));
var virtualLineView, virtualLineSpot, canChangeVirtualLines = false;
if (doesWrap)
{
virtualLineView = getVirtualLineView(focusCaret[0]);
virtualLineSpot = virtualLineView.getVLineAndOffsetForChar(focusCaret[1]);
canChangeVirtualLines = ((up && virtualLineSpot.vline > 0) || ((!up) && virtualLineSpot.vline < (
virtualLineView.getNumVirtualLines() - 1)));
}
var newColByVirtualLineChange;
if (moveMode == "toEnd")
{
if (up)
{
focusCaret[0] = 0;
focusCaret[1] = 0;
}
else
{
focusCaret[0] = rep.lines.length() - 1;
focusCaret[1] = lineLength(focusCaret[0]);
}
}
else if (moveMode == "byWord")
{
// move by "paragraph", a feature that Firefox lacks but IE and Safari both have
if (up)
{
if (focusCaret[1] == 0 && canChangeLines)
{
focusCaret[0]--;
focusCaret[1] = 0;
}
else focusCaret[1] = 0;
}
else
{
var lineLen = lineLength(focusCaret[0]);
if (browser.windows)
{
if (canChangeLines)
{
focusCaret[0]++;
focusCaret[1] = 0;
}
else
{
focusCaret[1] = lineLen;
}
}
else
{
if (focusCaret[1] == lineLen && canChangeLines)
{
focusCaret[0]++;
focusCaret[1] = lineLength(focusCaret[0]);
}
else
{
focusCaret[1] = lineLen;
}
}
}
savedFocusColumn = 0;
}
else if (canChangeVirtualLines)
{
var vline = virtualLineSpot.vline;
var offset = virtualLineSpot.offset;
if (up) vline--;
else vline++;
if (savedFocusColumn > offset) offset = savedFocusColumn;
else
{
savedFocusColumn = offset;
}
var newSpot = virtualLineView.getCharForVLineAndOffset(vline, offset);
focusCaret[1] = newSpot.lineChar;
}
else if (canChangeLines)
{
if (up) focusCaret[0]--;
else focusCaret[0]++;
var offset = focusCaret[1];
if (doesWrap)
{
offset = virtualLineSpot.offset;
}
if (savedFocusColumn > offset) offset = savedFocusColumn;
else
{
savedFocusColumn = offset;
}
if (doesWrap)
{
var newLineView = getVirtualLineView(focusCaret[0]);
var vline = (up ? newLineView.getNumVirtualLines() - 1 : 0);
var newSpot = newLineView.getCharForVLineAndOffset(vline, offset);
focusCaret[1] = newSpot.lineChar;
}
else
{
var lineLen = lineLength(focusCaret[0]);
if (offset > lineLen) offset = lineLen;
focusCaret[1] = offset;
}
}
else
{
if (up) focusCaret[1] = 0;
else focusCaret[1] = lineLength(focusCaret[0]);
savedFocusColumn = 0;
}
}
else if (keyCode == K_LEFT || keyCode == K_RIGHT)
{
var left = (keyCode == K_LEFT);
if (left)
{
if (moveMode == "toEnd") focusCaret[1] = 0;
else if (focusCaret[1] > 0)
{
if (moveMode == "byWord")
{
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], false);
}
else
{
focusCaret[1]--;
}
}
else if (focusCaret[0] > 0)
{
focusCaret[0]--;
focusCaret[1] = lineLength(focusCaret[0]);
if (moveMode == "byWord")
{
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], false);
}
}
}
else
{
var lineLen = lineLength(focusCaret[0]);
if (moveMode == "toEnd") focusCaret[1] = lineLen;
else if (focusCaret[1] < lineLen)
{
if (moveMode == "byWord")
{
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], true);
}
else
{
focusCaret[1]++;
}
}
else if (focusCaret[0] < rep.lines.length() - 1)
{
focusCaret[0]++;
focusCaret[1] = 0;
if (moveMode == "byWord")
{
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], true);
}
}
}
savedFocusColumn = 0;
}
}
var newSelFocusAtStart = ((focusCaret[0] < anchorCaret[0]) || (focusCaret[0] == anchorCaret[0] && focusCaret[1] < anchorCaret[1]));
var newSelStart = (newSelFocusAtStart ? focusCaret : anchorCaret);
var newSelEnd = (newSelFocusAtStart ? anchorCaret : focusCaret);
updatingSelectionNow = true;
performSelectionChange(markerfulLineAndChar(newSelStart[0], newSelStart[1]), markerfulLineAndChar(newSelEnd[0], newSelEnd[1]), newSelFocusAtStart);
updatingSelectionNow = false;
currentCallStack.userChangedSelection = true;
return true;
}
};
})());
// stolen from jquery-1.2.1 // stolen from jquery-1.2.1
function fixEvent(event) function fixEvent(event)
{ {
// store a copy of the original event object // store a copy of the original event object