Page 1 of 1

infinite loop in javascript mode

PostPosted: Tue Jul 10, 2012 4:19 am
by jaguarondi
Hello,

I try to see the problem 3696 in javascript mode.

I test this problem on IE 8, Chrome 12 and firefox 13. For all browsers, the js code start an infinite loop.

Analyse done with firebug: the loop is in sgf.js line 80. Seems the problem occurs when parsing the sfg.

Stack:
parseProperties(node=Object { _children=[0], FF="1", GM="1", more...})sgf.js (ligne 81)
parseNode(parent=Object { _children=[1]})sgf.js (ligne 62)
parseTree(curnode=Object { _children=[1]})sgf.js (ligne 45)
parseTree(curnode=Object { _children=[1]})sgf.js (ligne 48)
init(sgf="(\n;\nFF[1]\nGM[1]\nSZ[19]\n...W[kg]\n;\nB[kh]\nC[RIGHT])", completeFn=null)sgf.js (ligne 36)
SgfParser()sgf.js (ligne 15)
loadSgf(cfg=Object { progressiveLoad=false, markCurrent=true, markVariations=false, more...}, completeFn=function())player.js (ligne 365)
init(containerId="player-container", configuration=Object { dbId=3696, userId=5702, commentsURL="/util/jsoncomments.php?", more...}, callback=undefined)goproblems.js (ligne 158)
Player(containerId="player-container", configuration=Object { dbId=3696, userId=5702, commentsURL="/util/jsoncomments.php?", more...}, callback=undefined)goproblems.js (ligne 33)
(?)()3696?p...8235664 (ligne 311)
f(b=Document 3696?psetid=8235664, f=[function()])jquery.min.js (ligne 2)
f(b=Document 3696?psetid=8235664, c=[function()])jquery.min.js (ligne 2)
f(a=undefined)jquery.min.js (ligne 2)
f()jquery.min.js (ligne 2)[/list]

Sfg:
"(
;
FF[1]
GM[1]
SZ[19]
AP[Jago:Version 4.53]
AB[ij][ki][lj][lk][kk][jh][jj][ii]
AW[jk][ik][hk][jl][kl][ll][ml][mk][hj][hi][hh][ih][ig][nj][nh][ng][mf][lf][jf][nk][mg][if][ni][kf]
GN[david02]
;
B[lh]
;
W[mi]
;
B[li]
;
W[kg]
;
B[kh]
C[RIGHT])"

Actually, the script loop with the char from 192 to 194 = "\nB["
The code involve in the loop is the if at line 92 : if (this.firstNode && (key === "B" || key == "W")) {
this.firstNode=true, key="B" and this.index=194.
The line 105, this.index-=2;, restart the loop with index at 192.

There is a recent comment/modification at line 108 (maybe the key of the problem is there ;-) ):
// Maybe I should break? to force a new node?
// Matias Niklison, 12/6/2012.
continue;

Is sgf.js an original code from EidoGo or was it modified for goproblems ? In first case, I suppose the problem should reported to eidogo.

Re: infinite loop in javascript mode

PostPosted: Tue Jul 10, 2012 4:35 am
by jaguarondi
I try to set this.firstNode to false before the continue at line 110. This resolved the infinite loop but it also resolved the problem with success without playing it :lol:

Same bug with problem 2585.

Is it possible that the sfg is not formated correctly ?

Re: infinite loop in javascript mode

PostPosted: Tue Jul 10, 2012 4:53 am
by jaguarondi
When looking to working go problems, it seems the problem 3696 is resolved directly in js because there is only one sequence. Same for 2585.

So maybe set this.firstNode to false is correct. I have to find problem with infinite loop and more than one sequence to test it.

Re: infinite loop in javascript mode

PostPosted: Tue Jul 10, 2012 5:38 am
by jaguarondi
After reading a little more the js script, I think that the answers to line 108 "// Maybe I should break? to force a new node?" is yes. First set this.firstNode to false and then break instead of the continue at line 110.

Because we are in the same condition as the lines 88 and 89 are executed:
this.firstNode = false;
break;
stonesAdded and stonePlayed are true and this.index is set just before the first node to play.

But I can not test this correction with firebug (didn't find how to change the continue into break in firebug).

Re: infinite loop in javascript mode

PostPosted: Tue Jul 10, 2012 2:24 pm
by adum
thanks! we'll take a look

Re: infinite loop in javascript mode

PostPosted: Fri Aug 31, 2012 7:52 am
by Chango
Hi guys, I'm the developer in charge of the js player. First of all thanks for your help! second, sorry for the huge delay, but here is the solution:

All in sgf.js:
Code: Select all
-        if (this.firstNode) {
-          // stonesAdded flag: If there is a bunch of comments and information
-          // before the first stone is placed (AB, AW, B, or W), it keeps
-          // adding info to the same node until a stone is added.
-          var stonesAdded = false;
-          // stonePlayed flag: If there is a node that only has a comment (or
-          // some another non played stone (W or B)), it keeps
-          // adding info to the same node until the next move is a played a stone.
-          var stonePlayed = false;
-        }
+        // stonePlayed flag: If there is a node that only has a comment (or
+        // some another non played stone (W or B)), it keeps
+        // adding info to the same node until the next move is a played a stone.
+        var stonePlayed = false;
+        // stonesAdded flag: If there is a bunch of comments and information
+        // before the first stone is placed (AB, AW, B, or W), it keeps
+        // adding info to the same node until a stone is added.
+        // If this.firstNode is false, it is assumed that a stone has been
+        // added.
+        var stonesAdded = !this.firstNode;

I changed this as the 'stonePlayed' flag is going to be checked every time and stonesAdded only if its the first node. So the idea is that If someone does this:
Code: Select all
A[aa];C[Blah blah, I'm a Comment];B[bc]
, it will not affect the parsing.

Ok, then the infamous conditions:
Code: Select all
-                if (this.firstNode && (!stonesAdded || !stonePlayed)
-                    && c == ';') {
+                if (c == ';' && ((this.firstNode && !stonesAdded)
+                    || (!this.firstNode && !stonePlayed))) {
+                    // If it is the first node I must parse until a stone is
+                    // added.
+                    // If it's not the first node I must parse until a stone is
+                    // played.
                     this.index++;
                     continue;
                 }

So:
if it's he end of a node with no bifurcation and if it's the first node I have to continue until a stone is added. (A, B, AW or AB)
if it's he end of a node with no bifurcation and if it's not the first node I have to continue until a stone is played. (A or B)

The second if block changed is this:
Code: Select all
-                if (this.firstNode && (key === "B" || key == "W")) {
+                if (key === "B" || key == "W") {
                   // a stone has been played
                   stonePlayed = true;
-                  //           A[
-                  // I'm Here   ^
-                  //                    A[
-                  // so I go back here ^
-                  this.index-=2;
-                  // and clear the key.
-                  key = "";
-                  // Maybe I should break? to force a new node?
-                  // Matias Niklison, 12/6/2012.
-                  continue;
                 }

so there would be no need to go back, just keep tell me when a stone has been played.

And that's it.