Skip to content

Commit

Permalink
Fix Got [ERASED] expecting X when storage compacts while executing …
Browse files Browse the repository at this point in the history
…a function *in* storage on non-Bangle devices (fix #2431)
  • Loading branch information
gfwilliams committed Nov 22, 2023
1 parent f9a45f9 commit 903e938
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 10 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
Graphics: Graphics.stringMetrics now returns 'unrenderableChars/imageCount/maxImageHeight' for much more info about rendering strings
Graphics: wrapString now also wraps on slashes (to allow wrapping of URLs)
nRF5x: when connecting to other devices, allow a slave latency of 2 (might increase reliability)
Fix `Got [ERASED] expecting X` when storage compacts while executing a function *in* storage on non-Bangle devices (fix #2431)

2v19 : Fix Object.values/entries for numeric keys after 2v18 regression (fix #2375)
nRF52: for SD>5 use static buffers for advertising and scan response data (#2367)
Expand Down
7 changes: 6 additions & 1 deletion src/jsparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ NO_INLINE bool jspeFunctionDefinitionInternal(JsVar *funcVar, bool expressionOnl
if (!expressionOnly) {
int brackets = 0;
JsExecFlags oldExec = execInfo.execute;
execInfo.execute = EXEC_NO; // set no execute so we don't parse strings
execInfo.execute = EXEC_NO; // set no execute so we don't parse strings
while (lex->tk && (brackets || lex->tk != '}')) {
if (lex->tk == '{') brackets++;
if (lex->tk == '}') brackets--;
Expand Down Expand Up @@ -932,6 +932,11 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
}

jsvUnLock(thisVar);
/* It's possible that this call or a subcall may have compacted the filesystem
which changed the address the var in the iterator pointed to. If so we need to
copy it again. This should be quick-ish so lets' just do it rather than checking
whether we have compacted or not. https://github.com/espruino/Espruino/issues/2431 */
if (lex) jsvStringIteratorUpdatePtr(&lex->it);

return returnVar;
} else if (isParsing) { // ---------------------------------- function, but not executing - just parse args and be done
Expand Down
30 changes: 21 additions & 9 deletions src/jsvariterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,20 +265,16 @@ void jsvStringIteratorNew(JsvStringIterator *it, JsVar *str, size_t startIdx) {
it->var = jsvLockAgain(str);
it->varIndex = 0;
it->charsInVar = jsvGetCharactersInVar(it->var);

if (jsvIsFlatString(it->var)) {
it->ptr = jsvGetFlatStringPointer(it->var);
} else if (jsvIsNativeString(it->var)) {
it->ptr = (char*)it->var->varData.nativeStr.ptr;
#ifdef SPIFLASH_BASE
} else if (jsvIsFlashString(it->var)) {
if (jsvIsFlashString(it->var)) {
/* We need to handle flash strings separately as we want
to preload a buffer of data */
it->charsInVar = 0;
it->charIdx = startIdx; // if it's not UTF8 we can just load up the bit we want immediately
return jsvStringIteratorLoadFlashString(it);
#endif
} else{
it->ptr = &it->var->varData.str[0];
}
#endif
jsvStringIteratorUpdatePtr(it);
it->charIdx = startIdx;
jsvStringIteratorCatchUp(it);
}
Expand All @@ -300,6 +296,22 @@ void jsvStringIteratorNewUTF8(JsvStringIterator *it, JsVar *str, size_t startIdx
#endif
}

/// Update the pointer on a String iterator (should not normally be needed except when allocating a new iterator, but we may call it if we think the pointer in the var may have changed, eg during compaction)
void jsvStringIteratorUpdatePtr(JsvStringIterator *it) {
if (jsvIsFlatString(it->var)) {
it->ptr = jsvGetFlatStringPointer(it->var);
} else if (jsvIsNativeString(it->var)) {
it->ptr = (char*)it->var->varData.nativeStr.ptr;
#ifdef SPIFLASH_BASE
} else if (jsvIsFlashString(it->var)) {
/* don't do anything for flash strings - they are
handled specially in jsvStringIteratorNew */
#endif
} else if (it->var)
it->ptr = &it->var->varData.str[0];
else
it->ptr = 0;
}

void jsvStringIteratorClone(JsvStringIterator *dstit, JsvStringIterator *it) {
*dstit = *it;
Expand Down
3 changes: 3 additions & 0 deletions src/jsvariterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ void jsvStringIteratorNew(JsvStringIterator *it, JsVar *str, size_t startIdx);
/// Create a new String iterator from a string, starting from a specific character (ensures start character matches with actual UTF8 char number)
void jsvStringIteratorNewUTF8(JsvStringIterator *it, JsVar *str, size_t startIdx);

/// Update the pointer on a String iterator (should not normally be needed except when allocating a new iterator, but we may call it if we think the pointer in the var may have changed, eg during compaction)
void jsvStringIteratorUpdatePtr(JsvStringIterator *it);

/// Clone the string iterator
void jsvStringIteratorClone(JsvStringIterator *dstit, JsvStringIterator *it);

Expand Down

0 comments on commit 903e938

Please sign in to comment.