JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length) { JsVar *arrayBuffer = 0; // Only allow use of byteOffset/length if we're passing an ArrayBuffer - NOT A VIEW. bool copyData = false; if (jsvIsArrayBuffer(arr) && arr->varData.arraybuffer.type==ARRAYBUFFERVIEW_ARRAYBUFFER) { arrayBuffer = jsvLockAgain(arr); } else if (jsvIsNumeric(arr)) { length = jsvGetInteger(arr); byteOffset = 0; arrayBuffer = jswrap_arraybuffer_constructor((int)JSV_ARRAYBUFFER_GET_SIZE(type)*length); } else if (jsvIsArray(arr) || jsvIsArrayBuffer(arr)) { length = (JsVarInt)jsvGetLength(arr); byteOffset = 0; arrayBuffer = jswrap_arraybuffer_constructor((int)JSV_ARRAYBUFFER_GET_SIZE(type)*length); copyData = true; // so later on we'll populate this } if (!arrayBuffer) { jsExceptionHere(JSET_ERROR, "Unsupported first argument of type %t\n", arr); return 0; } if (length==0) { length = ((JsVarInt)jsvGetArrayBufferLength(arrayBuffer)-byteOffset) / (JsVarInt)JSV_ARRAYBUFFER_GET_SIZE(type); if (length<0) length=0; } JsVar *typedArr = jsvNewWithFlags(JSV_ARRAYBUFFER); if (typedArr) { typedArr->varData.arraybuffer.type = type; typedArr->varData.arraybuffer.byteOffset = (unsigned short)byteOffset; typedArr->varData.arraybuffer.length = (unsigned short)length; jsvSetFirstChild(typedArr, jsvGetRef(jsvRef(arrayBuffer))); if (copyData) { // if we were given an array, populate this ArrayBuffer JsvIterator it; jsvIteratorNew(&it, arr, JSIF_DEFINED_ARRAY_ElEMENTS); while (jsvIteratorHasElement(&it)) { JsVar *idx = jsvIteratorGetKey(&it); if (jsvIsInt(idx)) { JsVar *val = jsvIteratorGetValue(&it); // TODO: This is horrible! We need to try and iterate properly... jsvArrayBufferSet(typedArr, (size_t)jsvGetInteger(idx), val); jsvUnLock(val); } jsvUnLock(idx); jsvIteratorNext(&it); } jsvIteratorFree(&it); } } jsvUnLock(arrayBuffer); return typedArr; }
JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length) { JsVar *arrayBuffer = 0; if (jsvIsArrayBuffer(arr)) { arrayBuffer = jsvLockAgain(arr); } else if (jsvIsInt(arr)) { length = jsvGetInteger(arr); byteOffset = 0; arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length); } else if (jsvIsArray(arr)) { length = jsvGetArrayLength(arr); byteOffset = 0; arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length); // later on we'll populate this } if (!arrayBuffer) { jsError("Unsupported first argument\n"); return 0; } if (length<=0) length = (JsVarInt)jsvGetArrayBufferLength(arrayBuffer) / JSV_ARRAYBUFFER_GET_SIZE(type); JsVar *typedArr = jsvNewWithFlags(JSV_ARRAYBUFFER); if (typedArr) { typedArr->varData.arraybuffer.type = type; typedArr->varData.arraybuffer.byteOffset = (unsigned short)byteOffset; typedArr->varData.arraybuffer.length = (unsigned short)length; typedArr->firstChild = jsvGetRef(jsvRef(arrayBuffer)); if (jsvIsArray(arr)) { // if we were given an array, populate this ArrayBuffer JsvArrayIterator it; jsvArrayIteratorNew(&it, arr); while (jsvArrayIteratorHasElement(&it)) { JsVar *idx = jsvArrayIteratorGetIndex(&it); if (jsvIsInt(idx)) { JsVar *val = jsvArrayIteratorGetElement(&it); jsvArrayBufferSet(typedArr, jsvGetInteger(idx), val); jsvUnLock(val); } jsvUnLock(idx); jsvArrayIteratorNext(&it); } jsvArrayIteratorFree(&it); } } jsvUnLock(arrayBuffer); return typedArr; }
JsVar *_jswrap_array_map_or_forEach(JsVar *parent, JsVar *funcVar, JsVar *thisVar, bool isMap) { if (!jsvIsFunction(funcVar)) { jsError("Array.map's first argument should be a function"); return 0; } if (!jsvIsUndefined(thisVar) && !jsvIsObject(thisVar)) { jsError("Arraymap's second argument should be undefined, or an object"); return 0; } JsVar *array = 0; if (isMap) array = jsvNewWithFlags(JSV_ARRAY); if (array || !isMap) { JsVarRef childRef = parent->firstChild; while (childRef) { JsVar *child = jsvLock(childRef); if (jsvIsInt(child)) { JsVar *args[3], *mapped; args[0] = jsvLock(child->firstChild); // child is a variable name, create a new variable for the index args[1] = jsvNewFromInteger(jsvGetInteger(child)); args[2] = parent; mapped = jspeFunctionCall(funcVar, 0, thisVar, false, 3, args); jsvUnLock(args[0]); jsvUnLock(args[1]); if (mapped) { if (isMap) { JsVar *name = jsvCopyNameOnly(child, false/*linkChildren*/, true/*keepAsName*/); if (name) { // out of memory? name->firstChild = jsvGetRef(jsvRef(mapped)); jsvAddName(array, name); jsvUnLock(name); } } jsvUnLock(mapped); } } childRef = child->nextSibling; jsvUnLock(child); } } return array; }
/*JSON{ "type":"constructor", "class": "ArrayBuffer", "name": "ArrayBuffer", "description" : "Create an Array Buffer object", "generate" : "jswrap_arraybuffer_constructor", "params" : [ [ "byteLength", "int", "The length in Bytes" ] ], "return" : [ "JsVar", "An ArrayBuffer object" ] }*/ JsVar *jswrap_arraybuffer_constructor(JsVarInt byteLength) { if (byteLength <= 0 || byteLength>65535) { jsError("Invalid length for ArrayBuffer\n"); return 0; } if (byteLength > JSV_ARRAYBUFFER_MAX_LENGTH) { jsError("ArrayBuffer too long\n"); return 0; } JsVar *arrData = jsvNewStringOfLength((unsigned int)byteLength); if (!arrData) return 0; JsVar *arr = jsvNewWithFlags(JSV_ARRAYBUFFER); if (!arr) { jsvUnLock(arrData); return 0; } arr->firstChild = jsvGetRef(jsvRef(arrData)); jsvUnLock(arrData); arr->varData.arraybuffer.type = ARRAYBUFFERVIEW_ARRAYBUFFER; arr->varData.arraybuffer.byteOffset = 0; arr->varData.arraybuffer.length = (unsigned short)byteLength; return arr; }