Fix implicit casting to bool/number on ArrayBuffers (fix #1030)

This commit is contained in:
Gordon Williams 2017-01-23 11:05:24 +00:00
parent 7a8cd266f3
commit d8f53c5d74
4 changed files with 51 additions and 12 deletions

View File

@ -1,5 +1,6 @@
1v92 : nRF5x: Fix issue where Espruino could crash during save() if the flash got into a strange state
Added Pin.toggle() function
Fix implicit casting to bool/number on ArrayBuffers (fix #1030)
1v91 : Fix recent regression if no Boot Code defined at startup
Fix handling of return of rejected promise within a promise

View File

@ -1613,8 +1613,15 @@ JsVarInt jsvGetInteger(const JsVar *v) {
if (jsvIsNull(v)) return 0;
if (jsvIsUndefined(v)) return 0;
if (jsvIsIntegerish(v) || jsvIsArrayBufferName(v)) return v->varData.integer;
if (jsvIsArray(v) && jsvGetArrayLength(v)==1)
return jsvGetIntegerAndUnLock(jsvSkipNameAndUnLock(jsvGetArrayItem(v,0)));
if (jsvIsArray(v) || jsvIsArrayBuffer(v)) {
JsVarInt l = jsvGetLength((JsVar *)v);
if (l==0) return 0; // 0 length, return 0
if (l==1) {
if (jsvIsArrayBuffer(v))
return jsvGetIntegerAndUnLock(jsvArrayBufferGet((JsVar*)v,0));
return jsvGetIntegerAndUnLock(jsvSkipNameAndUnLock(jsvGetArrayItem(v,0)));
}
}
if (jsvIsFloat(v)) {
if (isfinite(v->varData.floating))
return (JsVarInt)(long long)v->varData.floating;
@ -1660,7 +1667,7 @@ void jsvSetInteger(JsVar *v, JsVarInt value) {
bool jsvGetBool(const JsVar *v) {
if (jsvIsString(v))
return jsvGetStringLength((JsVar*)v)!=0;
if (jsvIsFunction(v) || jsvIsArray(v) || jsvIsObject(v))
if (jsvIsFunction(v) || jsvIsArray(v) || jsvIsObject(v) || jsvIsArrayBuffer(v))
return true;
if (jsvIsFloat(v)) {
JsVarFloat f = jsvGetFloat(v);
@ -1673,10 +1680,14 @@ JsVarFloat jsvGetFloat(const JsVar *v) {
if (!v) return NAN; // undefined
if (jsvIsFloat(v)) return v->varData.floating;
if (jsvIsIntegerish(v)) return (JsVarFloat)v->varData.integer;
if (jsvIsArray(v)) {
JsVarInt l = jsvGetArrayLength(v);
if (jsvIsArray(v) || jsvIsArrayBuffer(v)) {
JsVarInt l = jsvGetLength(v);
if (l==0) return 0; // zero element array==0 (not undefined)
if (l==1) return jsvGetFloatAndUnLock(jsvSkipNameAndUnLock(jsvGetArrayItem(v,0)));
if (l==1) {
if (jsvIsArrayBuffer(v))
return jsvGetFloatAndUnLock(jsvArrayBufferGet((JsVar*)v,0));
return jsvGetFloatAndUnLock(jsvSkipNameAndUnLock(jsvGetArrayItem(v,0)));
}
}
if (jsvIsString(v)) {
char buf[64];
@ -1723,7 +1734,7 @@ bool jsvGetBoolAndUnLock(JsVar *v) { return _jsvGetBoolAndUnLock(v); }
#endif
/** Get the item at the given location in the array buffer and return the result */
size_t jsvGetArrayBufferLength(JsVar *arrayBuffer) {
size_t jsvGetArrayBufferLength(const JsVar *arrayBuffer) {
assert(jsvIsArrayBuffer(arrayBuffer));
return arrayBuffer->varData.arraybuffer.length;
}
@ -2451,7 +2462,7 @@ JsVar *jsvObjectSetOrRemoveChild(JsVar *obj, const char *name, JsVar *child) {
return child;
}
int jsvGetChildren(JsVar *v) {
int jsvGetChildren(const JsVar *v) {
//OPT: could length be stored as the value of the array?
int children = 0;
JsVarRef childref = jsvGetFirstChild(v);
@ -2486,7 +2497,7 @@ JsVarInt jsvSetArrayLength(JsVar *arr, JsVarInt length, bool truncate) {
return length;
}
JsVarInt jsvGetLength(JsVar *src) {
JsVarInt jsvGetLength(const JsVar *src) {
if (jsvIsArray(src)) {
return jsvGetArrayLength(src);
} else if (jsvIsArrayBuffer(src)) {

View File

@ -572,7 +572,7 @@ long long jsvGetLongIntegerAndUnLock(JsVar *v);
/** Get the item at the given location in the array buffer and return the result */
size_t jsvGetArrayBufferLength(JsVar *arrayBuffer);
size_t jsvGetArrayBufferLength(const JsVar *arrayBuffer);
/** Get the String the contains the data for this arrayBuffer */
JsVar *jsvGetArrayBufferBackingString(JsVar *arrayBuffer);
/** Get the item at the given location in the array buffer and return the result */
@ -666,13 +666,13 @@ void jsvObjectRemoveChild(JsVar *parent, const char *name);
* If the child is 0, the 'name' is also removed from the object */
JsVar *jsvObjectSetOrRemoveChild(JsVar *obj, const char *name, JsVar *child);
int jsvGetChildren(JsVar *v); ///< number of children of a variable. also see jsvGetArrayLength and jsvGetLength
int jsvGetChildren(const JsVar *v); ///< number of children of a variable. also see jsvGetArrayLength and jsvGetLength
JsVar *jsvGetFirstName(JsVar *v); ///< Get the first child's name from an object,array or function
/// Check if the given name is a child of the parent
bool jsvIsChild(JsVar *parent, JsVar *child);
JsVarInt jsvGetArrayLength(const JsVar *arr); ///< Not the same as GetChildren, as it can be a sparse array
JsVarInt jsvSetArrayLength(JsVar *arr, JsVarInt length, bool truncate); ///< set an array's length, optionally truncating if the array becomes shorter
JsVarInt jsvGetLength(JsVar *src); ///< General purpose length function. Does the 'right' thing
JsVarInt jsvGetLength(const JsVar *src); ///< General purpose length function. Does the 'right' thing
size_t jsvCountJsVarsUsed(JsVar *v); ///< Count the amount of JsVars used. Mostly useful for debugging
JsVar *jsvGetArrayIndex(const JsVar *arr, JsVarInt index); ///< Get a 'name' at the specified index in the array if it exists (and lock it)
JsVar *jsvGetArrayItem(const JsVar *arr, JsVarInt index); ///< Get an item at the specified index in the array if it exists (and lock it)

View File

@ -0,0 +1,27 @@
var tests=0, pass=0;
function t(expr, res) {
tests++;
var r = eval(expr);
if (r.toString()==res.toString())
pass++;
else
console.log(expr+" should equal "+res+" but got "+r);
}
// bool conversion
t("!!new Uint8Array([])",true)
t("!!new Uint8Array([0])",true)
t("!!new Uint8Array([1])",true)
t("!!new Uint8Array([1,2])",true)
// int/float conversion
t("new Uint8Array([1,2])-0",NaN)
t("0|new Uint8Array([])",0)
t("0|new Uint8Array([0])",0)
t("0|new Uint8Array([42])",42)
t("0|new Uint16Array([42])",42)
t("0|new Int16Array([42])",42)
t("new Float32Array([42])-0",42)
t("new Float64Array([1.2])-0",1.2)
result = tests==pass;