mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Fix crash when out of memory while creating built-in object
Fix continue statement in nested loops (fix #501)
This commit is contained in:
parent
eb88b79599
commit
f07c163fc7
@ -1,4 +1,6 @@
|
||||
1v75 : Fixed issue with Pins/Bools as Array indices
|
||||
Fix crash when out of memory while creating built-in object
|
||||
Fix continue statement in nested loops (fix #501)
|
||||
|
||||
1v74 : On Espruino Board, allow setTime to use full 64 bits so setTime(Date.parse("...")/1000) works
|
||||
Fixed issues with Waveform after 1v72 update to flat strings
|
||||
|
||||
@ -1088,7 +1088,7 @@ NO_INLINE void jspEnsureIsPrototype(JsVar *instanceOf, JsVar *prototypeName) {
|
||||
jsvUnLock(lastName);
|
||||
}
|
||||
JsVar *constructor = jsvFindChildFromString(prototypeVar, JSPARSE_CONSTRUCTOR_VAR, true);
|
||||
jsvSetValueOfName(constructor, instanceOf);
|
||||
if (constructor) jsvSetValueOfName(constructor, instanceOf);
|
||||
jsvUnLock(constructor);
|
||||
|
||||
jsvUnLock(prototypeVar);
|
||||
@ -1686,9 +1686,9 @@ NO_INLINE JsVar *jspeStatementDoOrWhile(bool isWhile) {
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
|
||||
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (execInfo.execute == EXEC_CONTINUE)
|
||||
if (execInfo.execute & EXEC_CONTINUE)
|
||||
execInfo.execute = EXEC_YES;
|
||||
if (execInfo.execute == EXEC_BREAK) {
|
||||
else if (execInfo.execute & EXEC_BREAK) {
|
||||
execInfo.execute = EXEC_YES;
|
||||
hasHadBreak = true; // fail loop condition, so we exit
|
||||
}
|
||||
@ -1721,9 +1721,9 @@ NO_INLINE JsVar *jspeStatementDoOrWhile(bool isWhile) {
|
||||
execInfo.execute |= EXEC_IN_LOOP;
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (execInfo.execute == EXEC_CONTINUE)
|
||||
if (execInfo.execute & EXEC_CONTINUE)
|
||||
execInfo.execute = EXEC_YES;
|
||||
if (execInfo.execute == EXEC_BREAK) {
|
||||
else if (execInfo.execute & EXEC_BREAK) {
|
||||
execInfo.execute = EXEC_YES;
|
||||
hasHadBreak = true;
|
||||
}
|
||||
@ -1744,6 +1744,7 @@ NO_INLINE JsVar *jspeStatementDoOrWhile(bool isWhile) {
|
||||
NO_INLINE JsVar *jspeStatementFor() {
|
||||
JSP_ASSERT_MATCH(LEX_R_FOR);
|
||||
JSP_MATCH('(');
|
||||
bool wasInLoop = execInfo.execute&EXEC_IN_LOOP;
|
||||
execInfo.execute |= EXEC_FOR_INIT;
|
||||
// initialisation
|
||||
JsVar *forStatement = 0;
|
||||
@ -1778,7 +1779,7 @@ NO_INLINE JsVar *jspeStatementFor() {
|
||||
execInfo.execute |= EXEC_IN_LOOP;
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
JslCharPos forBodyEnd = jslCharPosClone(&execInfo.lex->tokenStart);
|
||||
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
JSP_RESTORE_EXECUTE();
|
||||
|
||||
if (JSP_SHOULD_EXECUTE) {
|
||||
@ -1812,11 +1813,11 @@ NO_INLINE JsVar *jspeStatementFor() {
|
||||
jslSeekToP(execInfo.lex, &forBodyStart);
|
||||
execInfo.execute |= EXEC_IN_LOOP;
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
|
||||
if (execInfo.execute == EXEC_CONTINUE)
|
||||
if (execInfo.execute & EXEC_CONTINUE)
|
||||
execInfo.execute = EXEC_YES;
|
||||
if (execInfo.execute == EXEC_BREAK) {
|
||||
else if (execInfo.execute & EXEC_BREAK) {
|
||||
execInfo.execute = EXEC_YES;
|
||||
hasHadBreak = true;
|
||||
}
|
||||
@ -1878,12 +1879,14 @@ NO_INLINE JsVar *jspeStatementFor() {
|
||||
execInfo.execute |= EXEC_IN_LOOP;
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
JslCharPos forBodyEnd = jslCharPosClone(&execInfo.lex->tokenStart);
|
||||
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (execInfo.execute == EXEC_CONTINUE)
|
||||
execInfo.execute = EXEC_YES;
|
||||
if (execInfo.execute == EXEC_BREAK) {
|
||||
execInfo.execute = EXEC_YES;
|
||||
hasHadBreak = true;
|
||||
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (loopCond || !JSP_SHOULD_EXECUTE) {
|
||||
if (execInfo.execute & EXEC_CONTINUE)
|
||||
execInfo.execute = EXEC_YES;
|
||||
else if (execInfo.execute & EXEC_BREAK) {
|
||||
execInfo.execute = EXEC_YES;
|
||||
hasHadBreak = true;
|
||||
}
|
||||
}
|
||||
if (!loopCond) JSP_RESTORE_EXECUTE();
|
||||
if (loopCond) {
|
||||
@ -1908,10 +1911,10 @@ NO_INLINE JsVar *jspeStatementFor() {
|
||||
jslSeekToP(execInfo.lex, &forBodyStart);
|
||||
execInfo.execute |= EXEC_IN_LOOP;
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (execInfo.execute == EXEC_CONTINUE)
|
||||
if (!wasInLoop) execInfo.execute &= (JsExecFlags)~EXEC_IN_LOOP;
|
||||
if (execInfo.execute & EXEC_CONTINUE)
|
||||
execInfo.execute = EXEC_YES;
|
||||
if (execInfo.execute == EXEC_BREAK) {
|
||||
else if (execInfo.execute & EXEC_BREAK) {
|
||||
execInfo.execute = EXEC_YES;
|
||||
hasHadBreak = true;
|
||||
}
|
||||
@ -2112,7 +2115,7 @@ NO_INLINE JsVar *jspeStatement() {
|
||||
if (!(execInfo.execute & EXEC_IN_LOOP))
|
||||
jsExceptionHere(JSET_SYNTAXERROR, "CONTINUE statement outside of FOR or WHILE loop");
|
||||
else
|
||||
execInfo.execute = (execInfo.execute & (JsExecFlags)~EXEC_RUN_MASK) | EXEC_CONTINUE;
|
||||
execInfo.execute = (execInfo.execute & (JsExecFlags)~EXEC_RUN_MASK) | EXEC_CONTINUE;
|
||||
}
|
||||
} else if (execInfo.lex->tk==LEX_R_BREAK) {
|
||||
JSP_ASSERT_MATCH(LEX_R_BREAK);
|
||||
|
||||
@ -105,7 +105,7 @@ typedef enum {
|
||||
EXEC_RUN_MASK = EXEC_YES|EXEC_BREAK|EXEC_CONTINUE|EXEC_INTERRUPTED|EXEC_EXCEPTION,
|
||||
EXEC_ERROR_MASK = EXEC_INTERRUPTED|EXEC_ERROR|EXEC_EXCEPTION, // here, we have an error, but unless EXEC_NO_PARSE, we should continue parsing but not executing
|
||||
EXEC_NO_PARSE_MASK = EXEC_INTERRUPTED|EXEC_ERROR, // in these cases we should exit as fast as possible - skipping out of parsing
|
||||
EXEC_SAVE_RESTORE_MASK = EXEC_YES|EXEC_IN_LOOP|EXEC_IN_SWITCH | EXEC_ERROR_MASK, // the things JSP_SAVE/RESTORE_EXECUTE should keep track of
|
||||
EXEC_SAVE_RESTORE_MASK = EXEC_YES|EXEC_IN_LOOP|EXEC_IN_SWITCH|EXEC_CONTINUE|EXEC_BREAK | EXEC_ERROR_MASK, // the things JSP_SAVE/RESTORE_EXECUTE should keep track of
|
||||
EXEC_CTRL_C_MASK = EXEC_CTRL_C | EXEC_CTRL_C_WAIT, // Ctrl-C was pressed at some point
|
||||
} JsExecFlags;
|
||||
|
||||
|
||||
20
tests/test_continue_1.js
Normal file
20
tests/test_continue_1.js
Normal file
@ -0,0 +1,20 @@
|
||||
// https://github.com/espruino/Espruino/issues/501
|
||||
|
||||
// nested continue;
|
||||
|
||||
var r = 0;
|
||||
|
||||
for (var i=0; i < 10; ++i) {
|
||||
for (var j=0; j < 10; ++j);
|
||||
if(i==0) continue;
|
||||
r++;
|
||||
}
|
||||
|
||||
for (var i=0; i < 10; ++i) {
|
||||
for (var j=0; j < 10; ++j);
|
||||
if(i==1) continue;
|
||||
r++;
|
||||
}
|
||||
|
||||
|
||||
result = r==18;
|
||||
17
tests/test_continue_2.js
Normal file
17
tests/test_continue_2.js
Normal file
@ -0,0 +1,17 @@
|
||||
// https://github.com/espruino/Espruino/issues/501
|
||||
|
||||
var r=0;
|
||||
|
||||
for (var i=0; i < 10; ++i) {
|
||||
if(i==0) continue;
|
||||
for (var j=0; j < 0; ++j);
|
||||
r++;
|
||||
}
|
||||
|
||||
for (var i=0; i < 10; ++i) {
|
||||
if(i==1) continue;
|
||||
for (var j=0; j < 0; ++j);
|
||||
r++;
|
||||
}
|
||||
|
||||
result = r==18;
|
||||
Loading…
x
Reference in New Issue
Block a user