diff --git a/ChangeLog b/ChangeLog index d6aaa7bae..8081362e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,7 +12,7 @@ Turned 'http' into a library Added process.version and process.env (fix #131) Changed handling of 2nd arg of << so that precedence is correct - + Fixed handling of 'for (;;)' 1v42 : [ebirger] allowing 'new' with no brackets Allow built-in functions with variable numbers of arguments (fix #83) diff --git a/src/jsparse.c b/src/jsparse.c index e0680d7e6..7062158d5 100644 --- a/src/jsparse.c +++ b/src/jsparse.c @@ -1773,7 +1773,11 @@ JsVar *jspeStatementFor() { JSP_MATCH(LEX_R_FOR); JSP_MATCH('('); execInfo.execute |= EXEC_FOR_INIT; - JsVar *forStatement = jspeStatement(); // initialisation + // initialisation + JsVar *forStatement = 0; + // we could have 'for (;;)' - so don't munch up our semicolon if that's all we have + if (execInfo.lex->tk != ';') + forStatement = jspeStatement(); execInfo.execute &= (JsExecFlags)~EXEC_FOR_INIT; if (execInfo.lex->tk == LEX_R_IN) { // for (i in array) @@ -1864,12 +1868,14 @@ JsVar *jspeStatementFor() { jsvUnLock(forStatement); JSP_MATCH(';'); JslCharPos forCondStart = execInfo.lex->tokenStart; - JsVar *cond = jspeBase(); // condition - loopCond = JSP_SHOULD_EXECUTE && jsvGetBoolAndUnLock(jsvSkipName(cond)); - jsvUnLock(cond); + if (execInfo.lex->tk != ';') { + JsVar *cond = jspeBase(); // condition + loopCond = JSP_SHOULD_EXECUTE && jsvGetBoolAndUnLock(jsvSkipName(cond)); + jsvUnLock(cond); + } JSP_MATCH(';'); JslCharPos forIterStart = execInfo.lex->tokenStart; - { + if (execInfo.lex->tk != ')') { // we could have 'for (;;)' JSP_SAVE_EXECUTE(); jspSetNoExecute(); jsvUnLock(jspeBase()); // iterator @@ -1893,7 +1899,7 @@ JsVar *jspeStatementFor() { if (!loopCond) JSP_RESTORE_EXECUTE(); if (loopCond) { jslSeekTo(execInfo.lex, forIterStart); - jsvUnLock(jspeBase()); + if (execInfo.lex->tk != ')') jsvUnLock(jspeBase()); } while (!hasHadBreak && JSP_SHOULD_EXECUTE && loopCond #ifdef JSPARSE_MAX_LOOP_ITERATIONS @@ -1901,9 +1907,14 @@ JsVar *jspeStatementFor() { #endif ) { jslSeekTo(execInfo.lex, forCondStart); - cond = jspeBase(); - loopCond = jsvGetBoolAndUnLock(jsvSkipName(cond)); - jsvUnLock(cond); + ; + if (execInfo.lex->tk == ';') { + loopCond = true; + } else { + JsVar *cond = jspeBase(); + loopCond = jsvGetBoolAndUnLock(jsvSkipName(cond)); + jsvUnLock(cond); + } if (JSP_SHOULD_EXECUTE && loopCond) { jslSeekTo(execInfo.lex, forBodyStart); execInfo.execute |= EXEC_IN_LOOP; @@ -1918,7 +1929,7 @@ JsVar *jspeStatementFor() { } if (JSP_SHOULD_EXECUTE && loopCond) { jslSeekTo(execInfo.lex, forIterStart); - jsvUnLock(jspeBase()); + if (execInfo.lex->tk != ')') jsvUnLock(jspeBase()); } } jslSeekTo(execInfo.lex, forBodyEnd); diff --git a/tests/test_for_empty.js b/tests/test_for_empty.js new file mode 100644 index 000000000..e053b713d --- /dev/null +++ b/tests/test_for_empty.js @@ -0,0 +1,6 @@ + +a=42; +b=0; +for (;a;) { b++; a-- } + +result = b==42; diff --git a/tests/test_for_empty2.js b/tests/test_for_empty2.js new file mode 100644 index 000000000..a0d9810e0 --- /dev/null +++ b/tests/test_for_empty2.js @@ -0,0 +1,6 @@ + +a=42; +b=0; +for (;;) { b++; a--; if (!a) break; } + +result = b==42;