FF3.6 Stack output from Too Much Recursion

R

Richard Maher

Hi,

Sorry for labouring on this but I upgraded to FireFox 3.6 and managed to get
a bit more useful output that might ring a bell with somebody. The following
is a dump of the exception properties that was thrown from the code below
(Search for "4" to locate the source): -

Client: Error calling callback routine: -
Property: message Value: too much recursion
Property: fileName Value: http://192.168.1.190/tier3/Randomator.html
Property: lineNumber Value: 254
Property: stack Value:
()@http://192.168.1.190/tier3/Randomator.html:254
("3100369Lapointe, Hope FLarge Systems Engineering $57,410.00
$41,438.00")@http://192.168.1.190/tier3/Randomator.html:245
("3100369Lapointe, Hope FLarge Systems Engineering $57,410.00
$41,438.00",0,153)@http://192.168.1.190/tier3/Tier3Client.js:194
("30",[unknown
function],false)@http://192.168.1.190/tier3/Tier3Client.js:239
(12)@http://192.168.1.190/tier3/Randomator.html:328
Property: name Value: InternalError
toString() = InternalError: too much recursion
msgSlotId = 0
msgSeqNum = 153
responseMsg = 3100369Lapointe, Hope FLarge Systems Engineering $57,410.00
$41,438.00

As you may recall, the problem is that there is no recursion or at least
shouldn't be. If there is only one EmpPicker() in Ransomator.html (I'll
attach that again next) then the code runs all day as soon as there are two
or more then the code dies after 153 (150 to 155) iterations.

I've looked at about:config and can't see anything relevant but am led to
believe the FF stack depth to be 3000; either way I just can't see from that
"stack" output what it's complaining about :-(

This is the way the code/stack flows:-

Randomator.html calls the SEND("30",positionDiv,false) method on the
Tier3Client (T3Client) object line 328
Tier3Client.js "waits" at its applet call to "return chan.send" line 239
Tier3Client.js gets called back from the applet and does a callback.apply at
line 194
Randomator.html get screnn dimensions via "var canvas = " line 245
Randomator.html now varies the exact line of the exception around: -
254) height = window.innerHeight
265) if (typof window.pageYOffset ==
194) tier3Client.appendconsoleMessage

Any ideas what's happening? FF2 is fine, IE and Chrome do not exhibit this
problem :-(

1) Is "canvas" now a dodgy reserved word?
2) Is setTimeout with zero millises some sort of optimized "inline" call and
does not place a *non-recursive* event on the Event Dispatching Thread?

I have the console and FireBug off and the problem still occurs.

Cheers Richard Maher


/**
* Copyright (c) Richard Maher. All rights reserved.
*
* Tier3Client class bridges Javascript and Applet
* functionality.
*/

function Tier3Client(application,
codeBase,
port,
maxBuf,
hostCharSet,
sslReqd,
guiToolkit,
idleTimeout,
verbosity)
{
if (arguments.length < 4) {
throw new Error("Insufficient arguments for Tier3Client");
}

if (!navigator.javaEnabled()) {
alert("You must enable Java Applets in your browser\n" +
"before you can successfully access this page");
throw new Error("Java Applets are not enabled for browser");
}

this.application = application;
this.codeBase = codeBase;
this.port = port;
this.maxBuf = maxBuf;

this.hostCharSet = (hostCharSet == undefined) ? "ISO-8859-1" :
hostCharSet;
this.sslReqd = (sslReqd == undefined) ? "N" :
sslReqd;
this.guiToolkit = (guiToolkit == undefined) ? Tier3Client.GUIAWT :
guiToolkit;
this.idleTimeout = (idleTimeout == undefined) ? 0 :
idleTimeout;
this.verbosity = (verbosity == undefined) ? Tier3Client.WARNING :
verbosity;

var appletId = "Tier3__" + this.application + "_Applet";

try {
var idTaken = document.getElementById(appletId);
}
catch (err) {};

if (idTaken != null) {
throw new Error("Tier3 Client already registered for " +
this.application);
return;
}

var archiveName = "tier3Client.jar";
var className = "tier3Client/Tier3Application";

var appletParams = [{"name":"archive",
"value":archiveName },
{"name":"codebase",
"value":codeBase },
{"name":"code",
"value":className },
{"name":"java_version",
":"1.6+" },
{"name":"mayscript",
lue":"true" },
{"name":"scriptable",
ue":"true" },
{"name":"codebase_lookup",
"false" },
{"name":"APPLICATION",
"value":application },
{"name":"PORT",
"value":port },
{"name":"MAXBUF",
"value":maxBuf },
{"name":"HOSTCHARSET",
"value":this.hostCharSet},
{"name":"SSLREQD",
"value":this.sslReqd },
{"name":"GUITOOLKIT",
"value":this.guiToolkit },
{"name":"IDLETIMEOUT",
"value":this.idleTimeout},
{"name":"VERBOSITY",
"value":this.verbosity }];
var startParam = 0;

var objectTag = "<object classid=";

if (/Internet Explorer/.test(navigator.appName)) {
objectTag = objectTag +
'"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
} else {
objectTag = objectTag +
'"java:' + className + '.class" type="application/x-java-applet"
' +
'archive="' + codeBase + archiveName + '" ';
startParam = 1;
}

objectTag = objectTag + ' width= "0" height= "0" id="' + appletId +
'">';

for (i=startParam; i<appletParams.length; i++){
objectTag = objectTag + '<param name ="' + appletParams.name +
'" ' +
'value ="' + appletParams.value +
'">';
}

objectTag = objectTag + "</object>";

var appletDiv = document.createElement("div");
appletDiv.innerHTML = objectTag;

try {
document.body.appendChild(appletDiv);
this.chan = document.getElementById(appletId);
}
catch(err) {
alert("Tier3 unable to load applet for " + this.application +
": -\n" +
(err.description||err.message));
this.chan = null;
};
if (this.chan == null) {
throw new Error("Tier3 was unable to initialize the applet for " +
this.application);
} else {
try {
if (!this.chan.isAuthorized()) {
throw new Error("Tier3 User Authentication unsuccessful");
}
}
catch(err) {
this.chan.setAttribute("id",null);
this.chan = null;
throw new Error("Tier3 unable to load applet for " +
this.application + ": -\n" +
(err.description||err.message));
}
}

Tier3Client.applications[this.application] = this;
return this;
}

Tier3Client.FACPREFIX = "T3$";
Tier3Client.MAJVERS = 1;
Tier3Client.MINVERS = 0;
Tier3Client.GUIAWT = 1;
Tier3Client.DEBUG = 0;
Tier3Client.INFO = 1;
Tier3Client.WARNING = 2;
Tier3Client.ERROR = 3;
Tier3Client.FATAL = 4;

Tier3Client.errorPage = "Tier3Error.html";
Tier3Client.logoffPage = "Tier3Logoff.html";

Tier3Client.launder =
function(jsobject) {
return jsobject;
};

Tier3Client.prototype = {

send:
function(msgBody, callback, async)
{
if (arguments.length < 2) {
throw new Error("Insufficient arguments for send(msgBody,
callback)");
}

if (typeof callback != "function") {
throw new Error("The 'callback' parameter must be a
function");
}

var noWait = true;
if (arguments.length > 2) {
if (typeof async != "boolean") {
throw new Error("The 'async' parameter must be a
boolean");
}
noWait = async;
}

var chan = this.chan;
var callbackArgs = new Array();
var responseCnt = 0;
var i = 0;

var msgCandidate =
{
msgSlotId : -1,
msgSeqNum : -1,
chan : chan,
callback : callback,
callbackArgs : callbackArgs,

dispatcher :
function(responseMsg,
msgSlotId,
msgSeqNum)
{
fadeSecs.value = msgSeqNum;
empsCnt.value = "1";
empsCnt.value = "1.1";
this.responseCnt++;
empsCnt.value = "1a";
this.msgSlotId = msgSlotId;
empsCnt.value = "1b";
this.msgSeqNum = msgSeqNum;
empsCnt.value = "1c";
callbackArgs[0] = responseMsg;

try {
empsCnt.value = "2";
callback.apply(this, callbackArgs);
empsCnt.value = "3";
}
catch (err) {
empsCnt.value = "4";
var errMsg = "Error calling callback
routine: -\n";
for (var prop in err) {
errMsg += " Property: " + prop + " Value: " +
err[prop] + "\n";
}
errMsg += " toString() = " + err.toString() +
"\n";
errMsg += " msgSlotId = " + msgSlotId + "
msgSeqNum = " + msgSeqNum + "\n";
errMsg += " responseMsg = " + responseMsg;

// console.log("Client: " + errMsg);
document.write("Client: " + errMsg);
empsCnt.value = "5";
this.chan.appendConsoleMsg("Client: " +
errMsg);
empsCnt.value = "6";

throw new Error(errMsg);
}
empsCnt.value = "7";
},

getMsgSeqNum :
function() {
return this.msgSeqNum;
},

getResponseCnt:
function() {
return this.responseCnt;
},

rendezvous :
function() {
return chan.rendezvous();
}

};

for (i=3; i<arguments.length; i++) {
callbackArgs[i - 2] = arguments;
}

return chan.send(msgCandidate, msgBody, noWait);
},

appendConsoleMsg:
function(msg)
{
this.chan.appendConsoleMsg(msg);
}
};

Tier3Client.applications = {};
 
R

Richard Maher

Here's the main web-page "Randomator.html": -

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta name = "author"
content = "Richard Maher"/>
<meta name = "description"
content = "Tier3Client random Employee picker"/>

<style>

html
{
height: 100%
}

body
{
background-color: Gray;
margin: 0px;
padding: 0px;
}

input.knob
{
font-family: arial;
font-weight: bold;
background-color: DarkGray;
color: black;
font-size: 18px;
height: 26px;
width: 20px;
padding: 0px;
margin: 1px;
}

.cntr
{
font-family: georgia;
font-weight: bold;
font-size: 18px;
background-color: white;
color: black;
height: 20px;
width: 30px;
text-align: center;
}

table#empDetails caption
{
font-family: Arial;
font-weight: bold;
font-size: 12px;
color: gray;
}

table#empDetails
{
width: 100%;
}

.promptItem
{
text-align: right;
}

.dataItem
{
font-weight: bold;
}

div#ctrlPanel
{
background-color: Turquoise;
color: black;
font-family: Georgia;
font-size: 12px;
margin: 0px;
padding: 0px;
border-style: solid;
border-width: 1px;
border-color: black;
height: 30px;
}

.screenHdr
{
text-align: center;
font-size: 22px;
font-weight: bold;
color: Black;
}

</style>

<script type="text/javascript" src="Tier3Client.js" ></script>

<script type="text/javascript">

var t3Client;
var fadeSecs;
var empsCnt;

EmpPicker.FADEMIN = 1000;
EmpPicker.FADEMAX = 5000;
EmpPicker.MAXEMPS = 5;

EmpPicker.fadeDuration = 3000;
EmpPicker.activeDivs = [];

function EmpPicker()
{
var DIVCOLORS = new Array("lightgrey",
"yellow",
"magenta",
"lawngreen",
"cyan");
var FADEINTERVAL = 50;
var HDRHEIGHT = 30;
var DIVWIDTH = 300;
var DIVHEIGHT = 150;
var BORDERWIDTH = 4;

var targetDiv = document.createElement("div");
var startTime;
var endTime;
var fadeDuration;

var shuttingDown = false;

targetDiv.style.visibility = "hidden";
targetDiv.style.position = "absolute";
targetDiv.style.width = DIVWIDTH+"px";
targetDiv.style.height = DIVHEIGHT+"px";

var colorIndex = EmpPicker.activeDivs.length %
DIVCOLORS.length;
targetDiv.style.backgroundColor
= DIVCOLORS[colorIndex];

targetDiv.style.color = "black";
targetDiv.style.fontSize = "12px";
targetDiv.style.borderTop = "1px solid black";
targetDiv.style.borderRight= "3px solid black";
targetDiv.style.borderBottom
= "3px solid black";
targetDiv.style.borderLeft = "1px solid black";
targetDiv.style.padding = "0px";
targetDiv.style.margin = "0px";

document.body.appendChild(targetDiv);

var eventsMgr = function()
{
var AST = 0;

var setAST =
function(entryPoint,timer){
AST = setTimeout(entryPoint,timer);
};

var cancelAST =
function(){
clearTimeout(AST);
};

return {
setAST : setAST,
cancelAST : cancelAST
};
}();

var positionDiv =
function(respMsg)
{
// console.log("SeqNum = " + this.msgSeqNum);
fadeSecs.value = this.msgSeqNum;
// console.log("after rendezvous");
if (shuttingDown){
// this.rendezvous();
// alert("PD exit");
return;
}

targetDiv.style.visibility = "hidden";
targetDiv.style.opacity = "";
targetDiv.style.filter = "";
targetDiv.style.zIndex = "1000";

var recType = respMsg.substr(0,2);

// t3Client.appendConsoleMsg("Checking recType [" + recType + "]");
// console.log("Checking recType [" + recType + "]");
switch (recType)
{
case "00" :
// alert(respMsg.substr(2));
this.rendezvous();
t3Client.appendConsoleMsg("got error");
break;
case "31" :
// t3Client.appendConsoleMsg("setting target Div");
// console.log("setting target Div");
try {
targetDiv.innerHTML =
'<table border="0" cellpadding="1px" '
+
' align="center" id="empDetails"> '
+
' <caption>Totally Random Employee</caption>'
+
' <tr><td class="promptItem">Employee Id: </td>'
+
' <td class="dataItem">'+ respMsg.substr(2,5)
+'</td></tr>' +
' <tr><td class="promptItem"> Name:</td>'
+
' <td class="dataItem">'+ respMsg.substr(7,28)
+'</td></tr>' +
' <tr><td class="promptItem">Sex: </td>'
+
' <td class="dataItem">'+ respMsg.substr(35,1)
+'</td></tr>' +
' <tr><td span class="promptItem">Department: </td>'
+
' <td class="dataItem">'+ respMsg.substr(36,30)
+'</td></tr>' +
' <tr><td class="promptItem">Current Salary: </td>'
+
' <td class="dataItem">'+ respMsg.substr(66,12)
+'</td></tr>' +
' <tr><td class="promptItem">Dept Average: </td>'
+
' <td class="dataItem">'+ respMsg.substr(78,12)
+'</td></tr>' +
'</table><br>';
}catch (err) {
this.rendezvous();
var errMsg = "Error calling setting DIV: -\n";
for (var prop in err) {
errMsg += " Property: " + prop + " Value: " +
err[prop] + "\n";
}
errMsg += " toString() = " + err.toString() +
"\n";
t3Client.appendConsoleMsg(errMsg);
// console.log(errMsg);
throw new Error(errMsg);
}
// t3Client.appendConsoleMsg("after target Div");
// console.log("after target Div");
break;
default :
throw new Error("Received Invalid Record Type [" + recType +
"]");
}
// t3Client.appendConsoleMsg("after recType");
// console.log("after recType");

var canvas = function(){

var height = 0;
var width = 0;
var scrollTop = 0;
var scrollLeft = 0;

if (window.innerHeight){
width = window.innerWidth;
height = window.innerHeight;
}
else if (document.documentElement &&
document.documentElement.clientHeight){
width = document.documentElement.clientWidth;
height = document.documentElement.clientHeight;
}
else if (document.body){
width = document.body.clientWidth;
height = document.body.clientHeight;
}

if (typeof( window.pageYOffset ) == 'number'){
scrollTop = window.pageYOffset;
scrollLeft = window.pageXOffset;
}
else if (document.documentElement &&
document.documentElement.scrollTop){
scrollTop = document.documentElement.scrollTop;
scrollLeft = document.documentElement.scrollLeft;
}
else if (document.body){
scrollTop = document.body.scrollTop;
scrollLeft = document.body.scrollLeft;
}

return {height : height, width : width, scrollTop : scrollTop,
scrollLeft : scrollLeft};

}();

// console.log("after canvass");

var divTop = Math.floor(Math.random()*(canvas.height -
(DIVHEIGHT + BORDERWIDTH + HDRHEIGHT)));
divTop = divTop < 0 ? 0 : divTop;
var divLeft = Math.floor(Math.random()*(canvas.width -
(DIVWIDTH + BORDERWIDTH)));
divLeft = divLeft < 0 ? 0 : divLeft;

targetDiv.style.left = divLeft + "px";
targetDiv.style.top = (divTop + HDRHEIGHT) + "px";
targetDiv.style.visibility = "visible";

startTime = new Date().getTime();
endTime = startTime + EmpPicker.fadeDuration;

this.rendezvous();
t3Client.appendConsoleMsg("after rendezvous" + this.msgSeqNum);
fadeDuration = EmpPicker.fadeDuration
// console.log("before setast");
eventsMgr.setAST(fadeIt,FADEINTERVAL);
// console.log("after setast");

}

var fadeIt =
function(){
var now = new Date().getTime();
if (now >= endTime) {
targetDiv.style.visibility = "hidden";
eventsMgr.setAST(carousel,300);
}else{
var fadeFactor = 1 - (now - startTime) / fadeDuration;
targetDiv.style.opacity = fadeFactor;
targetDiv.style.filter = "alpha(opacity="+(fadeFactor*100)+")";
targetDiv.style.zIndex--;
eventsMgr.setAST(fadeIt,FADEINTERVAL);
}
}

var carousel =
function(){
if (shuttingDown){
// alert("no go");
return;
}
t3Client.send("30",positionDiv,false);
}

this.shutdown =
function(){
shuttingDown = true;
eventsMgr.cancelAST();
targetDiv.style.visibility = "hidden";
document.body.removeChild(targetDiv);
targetDiv = null;
}

EmpPicker.activeDivs.push(this);
eventsMgr.setAST(carousel,0);

return this;
}

function load()
{
fadeSecs = document.getElementById("fadeSecs");
empsCnt = document.getElementById("empsCnt");

try {
t3Client = new Tier3Client(
"Demo", "http://192.168.1.159/Applets/",
2048, 1022, "ISO-8859-1", "N", Tier3Client.GUIAWT,
null,Tier3Client.WARNING);
} catch (err){
alert((err.description||err.message));
throw err;
}

if (t3Client == null || t3Client == undefined) {
alert("Error connecting to Tier3 Client")
throw new Error("Could not activate Tier3 Client");
}

fadeSecs.value = EmpPicker.fadeDuration / 1000;

t3Client.appendConsoleMsg("Employee Randomator successfully loaded");

addEmp();

return;
}

function setDuration(stepValue)
{
var newDuration = EmpPicker.fadeDuration + stepValue;
if (newDuration < EmpPicker.FADEMIN || newDuration >
EmpPicker.FADEMAX)
return;

EmpPicker.fadeDuration = newDuration;
fadeSecs.value = EmpPicker.fadeDuration / 1000;

}

function addEmp()
{
if (EmpPicker.activeDivs.length == EmpPicker.MAXEMPS)
return;

var newEmp = new EmpPicker();
empsCnt.value = EmpPicker.activeDivs.length;
}

function delEmp()
{
if (EmpPicker.activeDivs.length == 0)
return;

var victim = EmpPicker.activeDivs.pop();
victim.shutdown();

empsCnt.value = EmpPicker.activeDivs.length;

}

</script>

</head>
<body onload="load();" onunload="(function(){});">
<div id="ctrlPanel">
<table
style="table-layout: fixed;"
width="100%"
border="0"
frame="void"
cellpadding="0"
cellspacing="0"
rules="none"
<tr
valign="middle"
<td
width="40%"
style="text-align: right;"
valign="middle"
Fade Duration :
<input
type="button"
class="knob"
onclick="setDuration(1000)"
name="fadeUp"
value="^"
title="Increase Fade Time"
/>
<input
type="text"
class="cntr"
id="fadeSecs"
readonly="readonly"
value="0"
size=3
title="Duration of fade in seconds"
/>
<input
type="button"
class="knob"
style="font-size: 14px;"
onclick="setDuration(-1000)"
name="fadeDown"
value="v"
title="Decrease Fade Time"
/>
</td>
<td
width="20%"
class="screenHdr"
valign="middle"
>Randomator</td>

<td
width="40%"
style="text-align: left;"
valign="middle"
<input
type="button"
class="knob"
onclick="addEmp()"
name="empsUp"
value="^"
title="Pick more employees"
/>
<input
type="text"
class="cntr"
id="empsCnt"
readonly="readonly"
value="0"
size=3
title="Number of employees to pick"
/>
<input
type="button"
class="knob"
style="font-size: 14px;"
onclick="delEmp()"
name="empsDown"
value="v"
title="Pick fewer employees"
/>
: Concurrent Selections
</td>
</tr>
</table>
</div>
</body>
</html>
 
E

Evertjan.

Richard Maher wrote on 02 mrt 2010 in comp.lang.javascript:
<style>

html
{
height: 100%
}

body
{
background-color: Gray;
margin: 0px;
padding: 0px;
}

No doubt this will strengthen the motivation of professionals,
especially the html height of 100%,
but it is far away from javascript, isn't it?
 
R

Richard Maher

Hi Stefan,

Stefan Weiss said:
I don't have FF 3.6 available for testing, but I've experienced this
error sporadically in FF 3.0. In my case, I had suspected Firebug (I
think we talked about this before, not sure), but it could easily have
been something else. By the time I reactivated Firebug, it had been
updated, and the problem had disappeared: correlation, but not
necessarily causation.

The very first thing I would try: disable *all* Firefox add-ons, and I
mean really disable and restart.

Done, but still no joy I'm afraid :-(
A few weeks ago, I spent most of an
afternoon tracking down a weird JavaScript error ("e is not defined"),
and when I finally found the source, it turned out to be a typo in the
NoScript add-on. If you can eliminate the possibility of an error
outside your own code, that would help narrow it down. If you could
reproduce the error with Java disabled, that would be even better, but I
don't know if that's possible in your application.

Jorge was good enough to try that (see below for details) but unfortunately
when the JAVA applet is removed from the equation it all seems to work. It
looks like I'll have to try and come up with a scaled-down Applet
reproducer.

OK, with HTML5 support appearing I thought I'd clutch at that straw :)
Don't know how to answer that, because I can't look into your applet and
browsers don't have an EDT (well, maybe HotJava does). I don't know what
you mean by "optimized inline call", there's no such thing in
JavaScript.

I was dreaming that a setTimeout(x.0); was being optimized to x(); resulting
in "x" being executed inline and that might possibly explain the recursion
that I am yet to see! Ridiculous perhaps but I'm running short of options.
Calling window.setTimeout with 0 as the second argument
should result in the function being called "at the earliest
opportunity", after the main (=only) JS thread has become idle (and any
other functions queued with setTimeout have been called, if necessary).

Yes. So: -

function x(){
setTimeout(x,0); //Along the lines of what I'm doing
}

Does not induce any bloody form of recursion unlike: -

function x(){
x(); // This will crap out at 3000 (reported stack depth) on FF3.6
}

Which is what I'm *not* doing.

I guess I just wish someone who could read the Mozilla code could tell me
what FF3 considers a recursive check/condition (especially given the "stack"
property in the Exception that I included earlier) Once again the code *with
Applet* works fine with only one EmpPicker() selected/instantiated but when
another (up to 5) is introduced the "recursion" is trapped at around 153
iterations. The code is also happily chugging away on Chrome as we speak.

Why would multiple concurrent (Jorge's code can not induce the 1.5sec delay
my server can) timers flag a false recursion flag/exception when a sigle one
does not? And why only after 153 successful iterations?
Thanks for your continued interest and advice!

Cheers Richard Maher

Here's Jorge's "working" code (replacing the Applet bits in
Tier3Client.js): -



****FROM HERE****
On Jan 30, 11:01 am, "Richard Maher" <[email protected]>
wrote:
(...)

Removing the applet and the back-and-forth between Java-JS the
resulting java-less version seems to run fine:

http://jorgechamorro.com/cljs/095/

<script type="text/javascript">
function Tier3Client () {
(this.chan= {}).rendezvous= function () {
console.log("this.chan.rendezvous(), "+ (+new Date()));
};


this.chan.send= function (msgCandidate, msgBody, async) {
var r=
"31abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst­
u
vwxyz";
if (async) {
setTimeout(function () {
console.log("this.chan.send(async===true)");
msgCandidate.dispatcher(r, 0, 0);
}, (2e3*Math.random())|0);
} else {
console.log("this.chan.send(async===false)");
msgCandidate.dispatcher(r, 0, 0);
}
};


this.chan.appendConsoleMsg= function (p) {
console.log("appendConsoleMsg: "+ p);
};
}


(Tier3Client.prototype = {}).send= function (msgBody, callback,
async) {
var chan = this.chan;
var callbackArgs = [];
var i = 0;
var msgCandidate = {
dispatcher : function (responseMsg, msgSlotId, msgSeqNum) {
callbackArgs[0] = responseMsg;
callback.apply(this, callbackArgs);
},
rendezvous : function () {
console.log("msgCandidate.rendezvous(), "+ (+new Date()));
return chan.rendezvous();
}
};
for (i=3; i<arguments.length; i++) {
callbackArgs[i - 2] = arguments;
}
return chan.send(msgCandidate, msgBody, async);
};


Tier3Client.prototype.appendConsoleMsg= function (msg) {
console.log("Tier3Client.prototype.appendConsoleMsg(), "+ (+new
Date()));
this.chan.appendConsoleMsg(msg);
};
</script>
 
D

Dr J R Stockton

In comp.lang.javascript message <hmhhl0$m6b$1@news-
01.bur.connect.com.au>, Tue, 2 Mar 2010 07:17:48, Richard Maher
I've looked at about:config and can't see anything relevant but am led to
believe the FF stack depth to be 3000; either way I just can't see from that
"stack" output what it's complaining about :-(

This supports depth 3000; a modification of recursive factorial avoiding
large numbers. tested in Firefox 3.0.18 in WinXP sp3 :

function Sum(N) { if (N==0) return 0 ; return Sum(N-1) + 1 }

Sum(2999) // OK
Sum(3000) // !OK

Why should the stack have a fixed limit? It can be implemented as a
double-linked list, as (IIRC) in
<URL:http://www.merlyn.demon.co.uk/programs/longcalc.pas> (for which a
Delphi interpreter written in JavaScript would be fun).

Why to c.l.j.p? FU set to c.l.j only.
 
B

BGB / cr88192

Kevin McMurtrie said:
JavaScript is not Java.

yep.

IMO, it was an unfortunate historical choice for JavaScript to have been
named after Java, as this has created much needless confusion over the
years. if it were a slight variant of the same language, maybe, but it is
not...


in a way, it is about like the whole C, C++, and "C/C++" issue, where some
people think there is only a single language with different names, and some
others think there are in fact 3 languages...

well, and as well, some people who confuse them for assembler, or regard
them as some sort of esoteric black art, ...

 
R

Richard Maher

Richard Maher said:
Hi Stefan,

to
get

I don't have FF 3.6 available for testing, but I've experienced this
error sporadically in FF 3.0. In my case, I had suspected Firebug (I
think we talked about this before, not sure), but it could easily have
been something else. By the time I reactivated Firebug, it had been
updated, and the problem had disappeared: correlation, but not
necessarily causation.

The very first thing I would try: disable *all* Firefox add-ons, and I
mean really disable and restart.

Done, but still no joy I'm afraid :-(
A few weeks ago, I spent most of an
afternoon tracking down a weird JavaScript error ("e is not defined"),
and when I finally found the source, it turned out to be a typo in the
NoScript add-on. If you can eliminate the possibility of an error
outside your own code, that would help narrow it down. If you could
reproduce the error with Java disabled, that would be even better, but I
don't know if that's possible in your application.

Jorge was good enough to try that (see below for details) but unfortunately
when the JAVA applet is removed from the equation it all seems to work. It
looks like I'll have to try and come up with a scaled-down Applet
reproducer.

OK, with HTML5 support appearing I thought I'd clutch at that straw :) call
and Thread?

Don't know how to answer that, because I can't look into your applet and
browsers don't have an EDT (well, maybe HotJava does). I don't know what
you mean by "optimized inline call", there's no such thing in
JavaScript.

I was dreaming that a setTimeout(x.0); was being optimized to x(); resulting
in "x" being executed inline and that might possibly explain the recursion
that I am yet to see! Ridiculous perhaps but I'm running short of options.
Calling window.setTimeout with 0 as the second argument
should result in the function being called "at the earliest
opportunity", after the main (=only) JS thread has become idle (and any
other functions queued with setTimeout have been called, if necessary).

Yes. So: -

function x(){
setTimeout(x,0); //Along the lines of what I'm doing
}

Does not induce any bloody form of recursion unlike: -

function x(){
x(); // This will crap out at 3000 (reported stack depth) on FF3.6
}

Which is what I'm *not* doing.

I guess I just wish someone who could read the Mozilla code could tell me
what FF3 considers a recursive check/condition (especially given the "stack"
property in the Exception that I included earlier) Once again the code *with
Applet* works fine with only one EmpPicker() selected/instantiated but when
another (up to 5) is introduced the "recursion" is trapped at around 153
iterations. The code is also happily chugging away on Chrome as we speak.

Why would multiple concurrent (Jorge's code can not induce the 1.5sec delay
my server can) timers flag a false recursion flag/exception when a sigle one
does not? And why only after 153 successful iterations?
Thanks for your continued interest and advice!

Cheers Richard Maher

Here's Jorge's "working" code (replacing the Applet bits in
Tier3Client.js): -



****FROM HERE****
On Jan 30, 11:01 am, "Richard Maher" <[email protected]>
wrote:
(...)

Removing the applet and the back-and-forth between Java-JS the
resulting java-less version seems to run fine:

http://jorgechamorro.com/cljs/095/

<script type="text/javascript">
function Tier3Client () {
(this.chan= {}).rendezvous= function () {
console.log("this.chan.rendezvous(), "+ (+new Date()));
};


this.chan.send= function (msgCandidate, msgBody, async) {
var r=
"31abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst­
u
vwxyz";
if (async) {
setTimeout(function () {
console.log("this.chan.send(async===true)");
msgCandidate.dispatcher(r, 0, 0);
}, (2e3*Math.random())|0);
} else {
console.log("this.chan.send(async===false)");
msgCandidate.dispatcher(r, 0, 0);
}
};


this.chan.appendConsoleMsg= function (p) {
console.log("appendConsoleMsg: "+ p);
};
}


(Tier3Client.prototype = {}).send= function (msgBody, callback,
async) {
var chan = this.chan;
var callbackArgs = [];
var i = 0;
var msgCandidate = {
dispatcher : function (responseMsg, msgSlotId, msgSeqNum) {
callbackArgs[0] = responseMsg;
callback.apply(this, callbackArgs);
},
rendezvous : function () {
console.log("msgCandidate.rendezvous(), "+ (+new Date()));
return chan.rendezvous();
}
};
for (i=3; i<arguments.length; i++) {
callbackArgs[i - 2] = arguments;
}
return chan.send(msgCandidate, msgBody, async);
};


Tier3Client.prototype.appendConsoleMsg= function (msg) {
console.log("Tier3Client.prototype.appendConsoleMsg(), "+ (+new
Date()));
this.chan.appendConsoleMsg(msg);
};
</script>
--
Jorge.


****TO HERE****


I will put in the not insubstantial effort to come with (hopefully) a small
reproducer, but in the mean time here's a couple of bits of information that
might lead someone to explain to me why FireFox 3 is giving me "too much
recursion".

The architected JAVA and Javascript behaviour is as follows: -

Page Load:-
1) Javascript invokes an Applet Method (Creates a Tier3Client instance)
2) The Applet init() method does many things including create a Socket and a
Thread that reads from the socket

EmpPicker() Javascript Object (1 to 5 created on demand by the user): -
1) setTimeout(sendRequest,0)
2) sendRequest calls an Applet method specifying "callback" and then "wait"s
in Applet
3) Thread reading socket calls the Javascript callback routine
4) When ready, the Javascript "rendezvous()" method calls back into the
Applet and "notify"s the original sending thread that it can exit back to
Javascript
5) The callback routine then setTimeout(fadeIt,fadeInterval)
6) If we're still fading schedule another fade else schedule another READ
5b) The sendRequest is ready to recieve control back from the Applet but the
new JAVA plugin waits until the callback has returned to JAVA thus
preserving "conceptually, the single-threaded nature of today's modern
browsers".

For more JAVA/Javascript threading behaviour info, please see: -
http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/index.html#JS_J_THREADING

C'mon guys/gals, I bet you have the answer and can have a whole weeks House
supply of vicodin if you can just come up with a semi-resonable diagnosis!
(Not me dick-head, the problem :)

a) FireFox II is perfectly fine with it!
b) FireFox3 doesn't have any issues until more than one instance of
EmpPicker() is active.
c) Chrome have 5 EmpPickers going simultaneously for 20,000 iteractions and
no signes of distress
d) 148 is no where near 3000

So is something else using up the Stack space? It certainly doesn't report
as being corrupt.
Has FF3 introduced some too-clever-by-half stack monitor/walker thread to
proactively pounce on errant Javascript
Anyone seen a half-relevant release note?

Go on, take a shot, make a name for yourself, and most importantly save a
patient :)

Cheers Richard Maher
 
D

Dr J R Stockton

In comp.lang.javascript message
1) Is "canvas" now a dodgy reserved word?

That case-independent string does not appear in ECMA-262-5, which you
should have. It is in HTML5, and that part is implemented in Firefox
Opera Safari Chrome but not MSIE8.

In such cases, though, the easy thing is to change the string; try
"kansas" as a euphemism.
 
R

Richard Maher

Ok, can anyone recommend a FireFox-specific (or Mozilla?) support and/or
user forum?

https://support.mozilla.com/en-US/forum/1 Looks active. Any better?

Cheers Richard Maher

Richard Maher said:
Richard Maher said:
Hi Stefan,
managed
to

Done, but still no joy I'm afraid :-(


Jorge was good enough to try that (see below for details) but unfortunately
when the JAVA applet is removed from the equation it all seems to work. It
looks like I'll have to try and come up with a scaled-down Applet
reproducer. exhibit
this

OK, with HTML5 support appearing I thought I'd clutch at that straw :) call

I was dreaming that a setTimeout(x.0); was being optimized to x(); resulting
in "x" being executed inline and that might possibly explain the recursion
that I am yet to see! Ridiculous perhaps but I'm running short of options.
necessary).

Yes. So: -

function x(){
setTimeout(x,0); //Along the lines of what I'm doing
}

Does not induce any bloody form of recursion unlike: -

function x(){
x(); // This will crap out at 3000 (reported stack depth) on FF3.6
}

Which is what I'm *not* doing.

I guess I just wish someone who could read the Mozilla code could tell me
what FF3 considers a recursive check/condition (especially given the "stack"
property in the Exception that I included earlier) Once again the code *with
Applet* works fine with only one EmpPicker() selected/instantiated but when
another (up to 5) is introduced the "recursion" is trapped at around 153
iterations. The code is also happily chugging away on Chrome as we speak.

Why would multiple concurrent (Jorge's code can not induce the 1.5sec delay
my server can) timers flag a false recursion flag/exception when a sigle one
does not? And why only after 153 successful iterations?

Thanks for your continued interest and advice!

Cheers Richard Maher

Here's Jorge's "working" code (replacing the Applet bits in
Tier3Client.js): -



****FROM HERE****
On Jan 30, 11:01 am, "Richard Maher" <[email protected]>
wrote:
(...)

Removing the applet and the back-and-forth between Java-JS the
resulting java-less version seems to run fine:

http://jorgechamorro.com/cljs/095/

<script type="text/javascript">
function Tier3Client () {
(this.chan= {}).rendezvous= function () {
console.log("this.chan.rendezvous(), "+ (+new Date()));
};


this.chan.send= function (msgCandidate, msgBody, async) {
var r=
"31abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst­
u
vwxyz";
if (async) {
setTimeout(function () {
console.log("this.chan.send(async===true)");
msgCandidate.dispatcher(r, 0, 0);
}, (2e3*Math.random())|0);
} else {
console.log("this.chan.send(async===false)");
msgCandidate.dispatcher(r, 0, 0);
}
};


this.chan.appendConsoleMsg= function (p) {
console.log("appendConsoleMsg: "+ p);
};
}


(Tier3Client.prototype = {}).send= function (msgBody, callback,
async) {
var chan = this.chan;
var callbackArgs = [];
var i = 0;
var msgCandidate = {
dispatcher : function (responseMsg, msgSlotId, msgSeqNum) {
callbackArgs[0] = responseMsg;
callback.apply(this, callbackArgs);
},
rendezvous : function () {
console.log("msgCandidate.rendezvous(), "+ (+new Date()));
return chan.rendezvous();
}
};
for (i=3; i<arguments.length; i++) {
callbackArgs[i - 2] = arguments;
}
return chan.send(msgCandidate, msgBody, async);
};


Tier3Client.prototype.appendConsoleMsg= function (msg) {
console.log("Tier3Client.prototype.appendConsoleMsg(), "+ (+new
Date()));
this.chan.appendConsoleMsg(msg);
};
</script>
--
Jorge.


****TO HERE****


I will put in the not insubstantial effort to come with (hopefully) a small
reproducer, but in the mean time here's a couple of bits of information that
might lead someone to explain to me why FireFox 3 is giving me "too much
recursion".

The architected JAVA and Javascript behaviour is as follows: -

Page Load:-
1) Javascript invokes an Applet Method (Creates a Tier3Client instance)
2) The Applet init() method does many things including create a Socket and a
Thread that reads from the socket

EmpPicker() Javascript Object (1 to 5 created on demand by the user): -
1) setTimeout(sendRequest,0)
2) sendRequest calls an Applet method specifying "callback" and then "wait"s
in Applet
3) Thread reading socket calls the Javascript callback routine
4) When ready, the Javascript "rendezvous()" method calls back into the
Applet and "notify"s the original sending thread that it can exit back to
Javascript
5) The callback routine then setTimeout(fadeIt,fadeInterval)
6) If we're still fading schedule another fade else schedule another READ
5b) The sendRequest is ready to recieve control back from the Applet but the
new JAVA plugin waits until the callback has returned to JAVA thus
preserving "conceptually, the single-threaded nature of today's modern
browsers".

For more JAVA/Javascript threading behaviour info, please see: -
http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/index.html#JS_J_THREADING

C'mon guys/gals, I bet you have the answer and can have a whole weeks House
supply of vicodin if you can just come up with a semi-resonable diagnosis!
(Not me dick-head, the problem :)

a) FireFox II is perfectly fine with it!
b) FireFox3 doesn't have any issues until more than one instance of
EmpPicker() is active.
c) Chrome have 5 EmpPickers going simultaneously for 20,000 iteractions and
no signes of distress
d) 148 is no where near 3000

So is something else using up the Stack space? It certainly doesn't report
as being corrupt.
Has FF3 introduced some too-clever-by-half stack monitor/walker thread to
proactively pounce on errant Javascript
Anyone seen a half-relevant release note?

Go on, take a shot, make a name for yourself, and most importantly save a
patient :)

Cheers Richard Maher
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top