/*JSON{ "type" : "staticproperty", "class" : "process", "name" : "env", "generate" : "jswrap_process_env", "return" : ["JsVar","An object"] } Returns an Object containing various pre-defined variables. standard ones are BOARD, VERSION */ JsVar *jswrap_process_env() { JsVar *obj = jsvNewWithFlags(JSV_OBJECT); /* jsvUnLock(jsvObjectSetChild(obj, "VERSION", jsvNewFromString(JS_VERSION))); jsvUnLock(jsvObjectSetChild(obj, "BUILD_DATE", jsvNewFromString(__DATE__))); jsvUnLock(jsvObjectSetChild(obj, "BUILD_TIME", jsvNewFromString(__TIME__))); #ifdef GIT_COMMIT jsvUnLock(jsvObjectSetChild(obj, "GIT_COMMIT", jsvNewFromString(STRINGIFY(GIT_COMMIT)))); #endif jsvUnLock(jsvObjectSetChild(obj, "BOARD", jsvNewFromString(PC_BOARD_ID))); jsvUnLock(jsvObjectSetChild(obj, "CHIP", jsvNewFromString(PC_BOARD_CHIP))); jsvUnLock(jsvObjectSetChild(obj, "CHIP_FAMILY", jsvNewFromString(PC_BOARD_CHIP_FAMILY))); jsvUnLock(jsvObjectSetChild(obj, "FLASH", jsvNewFromInteger(FLASH_TOTAL))); jsvUnLock(jsvObjectSetChild(obj, "RAM", jsvNewFromInteger(RAM_TOTAL))); jsvUnLock(jsvObjectSetChild(obj, "SERIAL", jswrap_interface_getSerial())); jsvUnLock(jsvObjectSetChild(obj, "CONSOLE", jsvNewFromString(jshGetDeviceString(jsiGetConsoleDevice())))); */ JsVar *arr = jsvNewWithFlags(JSV_OBJECT); if (arr) { const char *s = exportNames; void **p = (void**)exportPtrs; while (*s) { jsvUnLock(jsvObjectSetChild(arr, s, jsvNewFromInteger((JsVarInt)(size_t)*p))); p++; while (*s) s++; // skip until 0 s++; // skip over 0 } jsvUnLock(jsvObjectSetChild(obj, "EXPORTS", arr)); } return obj; }
/*JSON{ "type" : "staticmethod", "class" : "Trig", "name" : "getTrigger", "generate" : "jswrap_trig_getTrigger", "params" : [ ["num","int","The trigger number (0..7)"] ], "return" : ["JsVar","A structure containing all information about the trigger"] } Get the current state of a trigger */ JsVar *jswrap_trig_getTrigger(JsVarInt num) { TriggerStruct *trig = &mainTrigger; if (num<0 || num>=TRIGGER_TRIGGERS_COUNT) { jsWarn("Invalid trigger number\n"); return 0; } TriggerPointStruct *tp = &trig->triggers[num]; // get offset in teeth JsVarFloat position = tp->tooth + (tp->toothFraction/256.0); // convert from teeth to degrees position = wrapAround((position * 360 / trig->teethTotal) + trig->keyPosition, 360); JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (!obj) return 0; JsVar *v; v = jsvNewFromFloat(position); jsvUnLock(jsvAddNamedChild(obj, v, "pos")); jsvUnLock(v); v = jsvNewFromFloat(jshGetMillisecondsFromTime(tp->pulseLength)); jsvUnLock(jsvAddNamedChild(obj, v, "pulseLength")); jsvUnLock(v); v = jsvNewWithFlags(JSV_ARRAY); int i; if (v) { for (i=0;i<TRIGGERPOINT_TRIGGERS_COUNT;i++) if (tp->pins[i] != PIN_UNDEFINED) { jsvArrayPushAndUnLock(v, jsvNewFromPin(tp->pins[i])); } } jsvUnLock(jsvAddNamedChild(obj, v, "pins")); jsvUnLock(v); return obj; }
/*JSON{ "type" : "method", "class" : "Pin", "name" : "getInfo", "ifndef" : "SAVE_ON_FLASH", "generate" : "jswrap_pin_getInfo", "return" : ["JsVar","An object containing information about this pins"] } Get information about this pin and its capabilities. Of the form: ``` { "port" : "A", // the Pin's port on the chip "num" : 12, // the Pin's number "in_addr" : 0x..., // (if available) the address of the pin's input address in bit-banded memory (can be used with peek) "out_addr" : 0x..., // (if available) the address of the pin's output address in bit-banded memory (can be used with poke) "analog" : { ADCs : [1], channel : 12 }, // If analog input is available "functions" : { "TIM1":{type:"CH1, af:0}, "I2C3":{type:"SCL", af:1} } } ``` Will return undefined if pin is not valid. */ JsVar *jswrap_pin_getInfo( JsVar *parent //!< The class instance representing the pin. ) { Pin pin = jshGetPinFromVar(parent); if (!jshIsPinValid(pin)) return 0; const JshPinInfo *inf = &pinInfo[pin]; JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (!obj) return 0; char buf[2]; buf[0] = (char)('A'+(inf->port-JSH_PORTA)); buf[1] = 0; jsvObjectSetChildAndUnLock(obj, "port", jsvNewFromString(buf)); jsvObjectSetChildAndUnLock(obj, "num", jsvNewFromInteger(inf->pin-JSH_PIN0)); #ifdef STM32 volatile uint32_t *addr; addr = jshGetPinAddress(pin, JSGPAF_INPUT); if (addr) jsvObjectSetChildAndUnLock(obj, "in_addr", jsvNewFromInteger((JsVarInt)addr)); addr = jshGetPinAddress(pin, JSGPAF_OUTPUT); if (addr) jsvObjectSetChildAndUnLock(obj, "out_addr", jsvNewFromInteger((JsVarInt)addr)); #endif // ADC if (inf->analog) { JsVar *an = jsvNewWithFlags(JSV_OBJECT); if (an) { JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (arr) { int i; for (i=0;i<ADC_COUNT;i++) if (inf->analog&(JSH_ANALOG1<<i)) jsvArrayPushAndUnLock(arr, jsvNewFromInteger(1+i)); jsvObjectSetChildAndUnLock(an, "ADCs", arr); } jsvObjectSetChildAndUnLock(obj, "channel", jsvNewFromInteger(inf->analog & JSH_MASK_ANALOG_CH)); } } JsVar *funcs = jsvNewWithFlags(JSV_OBJECT); if (funcs) { int i; for (i=0;i<JSH_PININFO_FUNCTIONS;i++) { if (inf->functions[i]) { JsVar *func = jsvNewWithFlags(JSV_OBJECT); if (func) { char buf[16]; jshPinFunctionToString(inf->functions[i], JSPFTS_TYPE, buf, sizeof(buf)); jsvObjectSetChildAndUnLock(func, "type", jsvNewFromString(buf)); jsvObjectSetChildAndUnLock(func, "af", jsvNewFromInteger(inf->functions[i] & JSH_MASK_AF)); jshPinFunctionToString(inf->functions[i], JSPFTS_DEVICE|JSPFTS_DEVICE_NUMBER, buf, sizeof(buf)); jsvObjectSetChildAndUnLock(funcs, buf, func); } } } jsvObjectSetChildAndUnLock(obj, "functions", funcs); } return obj; }
JsVar *jswrap_arguments() { JsVar *scope = 0; if (execInfo.scopeCount>0) scope = jsvLock(execInfo.scopes[execInfo.scopeCount-1]); if (!jsvIsFunction(scope)) { jsvUnLock(scope); jsError("Can only use 'arguments' variable inside a function"); return 0; } JsVar *args = jsvNewWithFlags(JSV_ARRAY); if (!args) return 0; // out of memory JsvObjectIterator it; jsvObjectIteratorNew(&it, scope); while (jsvObjectIteratorHasElement(&it)) { JsVar *idx = jsvObjectIteratorGetKey(&it); if (jsvIsFunctionParameter(idx)) { JsVar *val = jsvSkipOneName(idx); jsvArrayPushAndUnLock(args, val); } jsvUnLock(idx); jsvObjectIteratorNext(&it); } jsvObjectIteratorFree(&it); jsvUnLock(scope); return args; }
/*JSON{ "type" : "method", "ifndef" : "SAVE_ON_FLASH", "class" : "RegExp", "name" : "exec", "params" : [ ["str","JsVar","A string to match on"] ], "generate" : "jswrap_regexp_exec", "return" : ["JsVar","A result array, or null"] } Test this regex on a string - returns a result array on success, or `null` otherwise. `/Wo/.exec("Hello World")` will return: ``` [ "Wo", "index": 6, "input": "Hello World" ] ``` Or with groups `/W(o)rld/.exec("Hello World")` returns: ``` [ "World", "o", "index": 6, "input": "Hello World" ] ``` */ JsVar *jswrap_regexp_exec(JsVar *parent, JsVar *arg) { JsVar *str = jsvAsString(arg); JsVarInt lastIndex = jsvGetIntegerAndUnLock(jsvObjectGetChild(parent, "lastIndex", 0)); JsVar *regex = jsvObjectGetChild(parent, "source", 0); if (!jsvIsString(regex)) { jsvUnLock2(str,regex); return 0; } size_t regexLen = jsvGetStringLength(regex); char *regexPtr = (char *)alloca(regexLen+1); if (!regexPtr) { jsvUnLock2(str,regex); return 0; } jsvGetString(regex, regexPtr, regexLen+1); jsvUnLock(regex); JsVar *rmatch = match(regexPtr, str, (size_t)lastIndex, jswrap_regexp_hasFlag(parent,'i')); jsvUnLock(str); if (!rmatch) { rmatch = jsvNewWithFlags(JSV_NULL); lastIndex = 0; } else { // if it's global, set lastIndex if (jswrap_regexp_hasFlag(parent,'g')) { JsVar *matchStr = jsvGetArrayItem(rmatch,0); lastIndex = jsvGetIntegerAndUnLock(jsvObjectGetChild(rmatch, "index", 0)) + (JsVarInt)jsvGetStringLength(matchStr); jsvUnLock(matchStr); } else lastIndex = 0; } jsvObjectSetChildAndUnLock(parent, "lastIndex", jsvNewFromInteger(lastIndex)); return rmatch; }
/*JSON{ "type" : "method", "class" : "String", "name" : "split", "generate" : "jswrap_string_split", "params" : [ ["separator","JsVar","The start character index"] ], "return" : ["JsVar","Part of this string from start for len characters"] } Return an array made by splitting this string up by the separator. eg. ```'1,2,3'.split(',')==[1,2,3]``` */ JsVar *jswrap_string_split(JsVar *parent, JsVar *split) { JsVar *array = jsvNewWithFlags(JSV_ARRAY); if (!array) return 0; // out of memory if (jsvIsUndefined(split)) { jsvArrayPush(array, parent); return array; } split = jsvAsString(split, false); int idx, last = 0; int splitlen = jsvIsUndefined(split) ? 0 : (int)jsvGetStringLength(split); int l = (int)jsvGetStringLength(parent) + 1 - splitlen; for (idx=0;idx<=l;idx++) { if (splitlen==0 && idx==0) continue; // special case for where split string is "" if (idx==l || splitlen==0 || jsvCompareString(parent, split, (size_t)idx, 0, true)==0) { if (idx==l) { idx=l+splitlen; // if the last element, do to the end of the string if (splitlen==0) break; } JsVar *part = jsvNewFromStringVar(parent, (size_t)last, (size_t)(idx-last)); if (!part) break; // out of memory jsvArrayPush(array, part); jsvUnLock(part); last = idx+splitlen; } } jsvUnLock(split); return array; }
JsVar *jswrap_process_memory() { jsvGarbageCollect(); JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (obj) { unsigned int history = 0; JsVar *historyVar = jsvObjectGetChild(execInfo.hiddenRoot, JSI_HISTORY_NAME, 0); if (historyVar) { history = (unsigned int)jsvCountJsVarsUsed(historyVar); // vars used to store history jsvUnLock(historyVar); } unsigned int usage = jsvGetMemoryUsage() - history; unsigned int total = jsvGetMemoryTotal(); jsvUnLock(jsvObjectSetChild(obj, "free", jsvNewFromInteger((JsVarInt)(total-usage)))); jsvUnLock(jsvObjectSetChild(obj, "usage", jsvNewFromInteger((JsVarInt)usage))); jsvUnLock(jsvObjectSetChild(obj, "total", jsvNewFromInteger((JsVarInt)total))); jsvUnLock(jsvObjectSetChild(obj, "history", jsvNewFromInteger((JsVarInt)history))); #ifdef ARM jsvUnLock(jsvObjectSetChild(obj, "stackEndAddress", jsvNewFromInteger((JsVarInt)(unsigned int)&_end))); jsvUnLock(jsvObjectSetChild(obj, "flash_start", jsvNewFromInteger((JsVarInt)FLASH_START))); jsvUnLock(jsvObjectSetChild(obj, "flash_binary_end", jsvNewFromInteger((JsVarInt)(unsigned int)&_etext))); jsvUnLock(jsvObjectSetChild(obj, "flash_code_start", jsvNewFromInteger((JsVarInt)FLASH_SAVED_CODE_START))); jsvUnLock(jsvObjectSetChild(obj, "flash_length", jsvNewFromInteger((JsVarInt)FLASH_TOTAL))); #endif } return obj; }
/*JSON{ "type" : "method", "class" : "Ethernet", "name" : "getIP", "generate" : "jswrap_ethernet_getIP", "return" : ["JsVar",""] } Get the current IP address, subnet, gateway and mac address. */ JsVar *jswrap_ethernet_getIP(JsVar *wlanObj) { NOT_USED(wlanObj); if (networkState != NETWORKSTATE_ONLINE) { jsError("Not connected to the internet"); return 0; } JsNetwork net; if (!networkGetFromVar(&net)) return 0; wiz_NetInfo gWIZNETINFO; ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO); /* If byte 1 is 0 we don't have a valid address */ JsVar *data = jsvNewWithFlags(JSV_OBJECT); networkPutAddressAsString(data, "ip", &gWIZNETINFO.ip[0], 4, 10, '.'); networkPutAddressAsString(data, "subnet", &gWIZNETINFO.sn[0], 4, 10, '.'); networkPutAddressAsString(data, "gateway", &gWIZNETINFO.gw[0], 4, 10, '.'); networkPutAddressAsString(data, "dns", &gWIZNETINFO.dns[0], 4, 10, '.'); networkPutAddressAsString(data, "mac", &gWIZNETINFO.mac[0], 6, 16, ':'); networkFree(&net); return data; }
/*JSON{ "type" : "staticmethod", "class" : "Object", "name" : "getOwnPropertyDescriptor", "generate" : "jswrap_object_getOwnPropertyDescriptor", "params" : [ ["obj","JsVar","The object"], ["name","JsVar","The name of the property"] ], "return" : ["JsVar","An object with a description of the property. The values of writable/enumerable/configurable may not be entirely correct due to Espruino's implementation."] } Get information on the given property in the object, or undefined */ JsVar *jswrap_object_getOwnPropertyDescriptor(JsVar *parent, JsVar *name) { if (!jswrap_object_hasOwnProperty(parent, name)) return 0; JsVar *varName = jspGetVarNamedField(parent, name, true); assert(varName); // we had it! (apparently) if (!varName) return 0; JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (!obj) { jsvUnLock(varName); return 0; } //jsvTrace(varName, 5); JsVar *var = jsvSkipName(varName); bool isBuiltIn = jsvIsNewChild(varName); JsvIsInternalChecker checkerFunction = jsvGetInternalFunctionCheckerFor(parent); jsvObjectSetChild(obj, "value", var); jsvUnLock(jsvObjectSetChild(obj, "writable", jsvNewFromBool(true))); jsvUnLock(jsvObjectSetChild(obj, "enumerable", jsvNewFromBool(!checkerFunction || !checkerFunction(varName)))); jsvUnLock(jsvObjectSetChild(obj, "configurable", jsvNewFromBool(!isBuiltIn))); jsvUnLock(var); jsvUnLock(varName); return obj; }
void jsvStringIteratorAppend(JsvStringIterator *it, char ch) { if (!it->var) return; if (it->charsInVar>0) { assert(it->charIdx+1 == it->charsInVar /* check at end */); it->charIdx++; } else assert(it->charIdx == 0); /* Note: jsvGetMaxCharactersInVar will return the wrong length when * applied to flat strings, but we don't care because the length will * be smaller than charIdx, which will force a new string to be * appended onto the end */ if (it->charIdx >= jsvGetMaxCharactersInVar(it->var)) { assert(!jsvGetLastChild(it->var)); JsVar *next = jsvNewWithFlags(JSV_STRING_EXT_0); if (!next) { jsvUnLock(it->var); it->var = 0; it->ptr = 0; it->charIdx = 0; return; // out of memory } // we don't ref, because StringExts are never reffed as they only have one owner (and ALWAYS have an owner) jsvSetLastChild(it->var, jsvGetRef(next)); jsvUnLock(it->var); it->var = next; it->ptr = &next->varData.str[0]; it->varIndex += it->charIdx; it->charIdx = 0; // it's new, so empty } it->ptr[it->charIdx] = ch; it->charsInVar = it->charIdx+1; jsvSetCharactersInVar(it->var, it->charsInVar); }
/*JSON{ "type" : "function", "name" : "setTimeout", "generate" : "jswrap_interface_setTimeout", "params" : [ ["function","JsVar","A Function or String to be executed"], ["timeout","float","The time until the function will be executed"], ["args","JsVarArray","Optional arguments to pass to the function when executed"] ], "return" : ["JsVar","An ID that can be passed to clearTimeout"] } Call the function (or evaluate the string) specified ONCE after the timeout in milliseconds. For instance: ``` setTimeout(function () { console.log("Hello World"); }, 1000); // or setTimeout('console.log("Hello World");', 1000); // both print 'Hello World' after a second ``` You can also specify extra arguments that will be sent to the function when it is executed. For example: ``` setTimeout(function (a,b) { console.log(a+" "+b); }, 1000, "Hello", "World"); // prints 'Hello World' after 1 second ``` If you want to stop the function from being called, pass the number that was returned by `setTimeout` into the `clearInterval` function. **Note:** If `setDeepSleep(true)` has been called and the interval is greater than 5 seconds, Espruino may execute the interval up to 1 second late. This is because Espruino can only wake from deep sleep every second - and waking early would cause Espruino to waste power while it waited for the correct time. */ JsVar *_jswrap_interface_setTimeoutOrInterval(JsVar *func, JsVarFloat interval, JsVar *args, bool isTimeout) { // NOTE: The 5 sec delay mentioned in the description is handled by jshSleep JsVar *itemIndex = 0; if (!jsvIsFunction(func) && !jsvIsString(func)) { jsExceptionHere(JSET_ERROR, "Function or String not supplied!"); } else { // Create a new timer JsVar *timerPtr = jsvNewWithFlags(JSV_OBJECT); if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL; JsSysTime intervalInt = jshGetTimeFromMilliseconds(interval); jsvObjectSetChildAndUnLock(timerPtr, "time", jsvNewFromLongInteger((jshGetSystemTime() - jsiLastIdleTime) + intervalInt)); if (!isTimeout) { jsvObjectSetChildAndUnLock(timerPtr, "interval", jsvNewFromLongInteger(intervalInt)); } jsvObjectSetChild(timerPtr, "callback", func); // intentionally no unlock if (jsvGetArrayLength(args)) jsvObjectSetChild(timerPtr, "args", args); // intentionally no unlock // Add to array itemIndex = jsvNewFromInteger(jsiTimerAdd(timerPtr)); jsvUnLock(timerPtr); jsiTimersChanged(); // mark timers as changed } return itemIndex; }
/*JSON{ "type":"staticmethod", "class": "Object", "name" : "keys", "description" : "Return all enumerable keys of the given object", "generate" : "jswrap_object_keys", "params" : [ [ "object", "JsVar", "The object to return keys for"] ], "return" : ["JsVar", "An array of strings - one for each key on the given object"] }*/ JsVar *jswrap_object_keys(JsVar *obj) { if (jsvIsIterable(obj)) { bool (*checkerFunction)(JsVar*) = 0; if (jsvIsFunction(obj)) checkerFunction = jsvIsInternalFunctionKey; else if (jsvIsObject(obj)) checkerFunction = jsvIsInternalObjectKey; JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (!arr) return 0; JsvIterator it; jsvIteratorNew(&it, obj); while (jsvIteratorHasElement(&it)) { JsVar *key = jsvIteratorGetKey(&it); if (!(checkerFunction && checkerFunction(key))) { JsVar *name = jsvCopyNameOnly(key,false,false); if (name) { jsvArrayPushAndUnLock(arr, name); } } jsvUnLock(key); jsvIteratorNext(&it); } jsvIteratorFree(&it); return arr; } else { jsWarn("Object.keys called on non-object"); return 0; } }
/*JSON{ "type":"method", "class": "String", "name" : "split", "description" : "Return an array made by splitting this string up by the separator. eg. ```'1,2,3'.split(',')==[1,2,3]```", "generate" : "jswrap_string_split", "params" : [ [ "separator", "JsVar", "The start character index"] ], "return" : ["JsVar", "Part of this string from start for len characters"] }*/ JsVar *jswrap_string_split(JsVar *parent, JsVar *split) { JsVar *array; int last, idx, arraylen=0; int splitlen = (int)jsvGetStringLength(split); int l = (int)jsvGetStringLength(parent) - splitlen; last = 0; array = jsvNewWithFlags(JSV_ARRAY); if (!array) return 0; // out of memory for (idx=0;idx<=l;idx++) { if (idx==l || jsvCompareString(parent, split, idx, 0, true)==0) { JsVar *part = jsvNewFromEmptyString(); if (!part) break; // out of memory JsVar *idxvar = jsvMakeIntoVariableName(jsvNewFromInteger(arraylen++), part); if (idxvar) { // could be out of memory if (idx==l) idx=l+splitlen; // if the last element, do to the end of the string jsvAppendStringVar(part, parent, last, idx-last); jsvAddName(array, idxvar); last = idx+splitlen; jsvUnLock(idxvar); } jsvUnLock(part); } } return array; }
/*JSON{ "type" : "method", "class" : "WLAN", "name" : "getIP", "generate" : "jswrap_wlan_getIP", "return" : ["JsVar",""] } Get the current IP address */ JsVar *jswrap_wlan_getIP(JsVar *wlanObj) { NOT_USED(wlanObj); if (networkState != NETWORKSTATE_ONLINE) { jsError("Not connected to the internet"); return 0; } JsNetwork net; if (!networkGetFromVar(&net)) return 0; tNetappIpconfigRetArgs ipconfig; netapp_ipconfig(&ipconfig); networkFree(&net); /* If byte 1 is 0 we don't have a valid address */ if (ipconfig.aucIP[3] == 0) return 0; JsVar *data = jsvNewWithFlags(JSV_OBJECT); networkPutAddressAsString(data, "ip", &ipconfig.aucIP[0], -4, 10, '.'); networkPutAddressAsString(data, "subnet", &ipconfig.aucSubnetMask[0], -4, 10, '.'); networkPutAddressAsString(data, "gateway", &ipconfig.aucDefaultGateway[0], -4, 10, '.'); networkPutAddressAsString(data, "dhcp", &ipconfig.aucDHCPServer[0], -4, 10, '.'); networkPutAddressAsString(data, "dns", &ipconfig.aucDNSServer[0], -4, 10, '.'); networkPutAddressAsString(data, "mac", &ipconfig.uaMacAddr[0], -6, 16, 0); return data; }
void httpIdle() { if (networkState != NETWORKSTATE_ONLINE) return; JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVERS,false); if (arr) { JsArrayIterator it; jsvArrayIteratorNew(&it, arr); while (jsvArrayIteratorHasElement(&it)) { JsVar *server = jsvArrayIteratorGetElement(&it); SOCKET socket = (SOCKET)jsvGetIntegerAndUnLock(jsvObjectGetChild(server,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined #ifndef USE_CC3000 // TODO: look for unreffed servers? fd_set s; FD_ZERO(&s); FD_SET(socket,&s); // check for waiting clients struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; int n = select(socket+1,&s,NULL,NULL,&timeout); #else /* CC3000 works a different way - we set accept as nonblocking, * and then we just call it and see if it works or not... */ int n=1; #endif while (n-->0) { // we have a client waiting to connect... int theClient = accept(socket,NULL,NULL); // try and connect if (theClient > -1) { JsVar *req = jspNewObject(jsiGetParser(), 0, "httpSRq"); JsVar *res = jspNewObject(jsiGetParser(), 0, "httpSRs"); if (res && req) { // out of memory? JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS, true); if (arr) { jsvArrayPush(arr, req); jsvUnLock(arr); } jsvObjectSetChild(req, HTTP_NAME_RESPONSE_VAR, res); jsvObjectSetChild(req, HTTP_NAME_SERVER_VAR, server); jsvUnLock(jsvObjectSetChild(req, HTTP_NAME_SOCKET, jsvNewFromInteger(theClient+1))); // on response jsvUnLock(jsvObjectSetChild(res, HTTP_NAME_CODE, jsvNewFromInteger(200))); jsvUnLock(jsvObjectSetChild(res, HTTP_NAME_HEADERS, jsvNewWithFlags(JSV_OBJECT))); } jsvUnLock(req); jsvUnLock(res); //add(new CNetworkConnect(theClient, this)); // add to service queue } } jsvUnLock(server); jsvArrayIteratorNext(&it); } jsvArrayIteratorFree(&it); jsvUnLock(arr); } httpServerConnectionsIdle(); httpClientConnectionsIdle(); }
JsVar *jswrap_interface_memory() { jsvGarbageCollect(); JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (obj) { unsigned int history = 0; JsVar *historyVar = jsvObjectGetChild(jsiGetParser()->root, JSI_HISTORY_NAME, 0); if (historyVar) { history = (unsigned int)jsvCountJsVarsUsed(historyVar); // vars used to store history jsvUnLock(historyVar); } unsigned int usage = jsvGetMemoryUsage() - history; unsigned int total = jsvGetMemoryTotal(); JsVar *v; v = jsvNewFromInteger(total-usage); jsvUnLock(jsvAddNamedChild(obj, v, "free")); jsvUnLock(v); v = jsvNewFromInteger(usage); jsvUnLock(jsvAddNamedChild(obj, v, "usage")); jsvUnLock(v); v = jsvNewFromInteger(total); jsvUnLock(jsvAddNamedChild(obj, v, "total")); jsvUnLock(v); v = jsvNewFromInteger(history); jsvUnLock(jsvAddNamedChild(obj, v, "history")); jsvUnLock(v); #ifdef ARM v = jsvNewFromInteger((JsVarInt)(unsigned int)&_end); jsvUnLock(jsvAddNamedChild(obj, v, "stackEndAddress")); jsvUnLock(v); #endif } return obj; }
void jsvStringIteratorAppend(JsvStringIterator *it, char ch) { if (!it->var) return; if (it->charsInVar>0) { assert(it->charIdx+1 == it->charsInVar /* check at end */); it->charIdx++; } else assert(it->charIdx == 0); if (it->charIdx >= jsvGetMaxCharactersInVar(it->var)) { assert(!jsvGetLastChild(it->var)); JsVar *next = jsvNewWithFlags(JSV_STRING_EXT_0); if (!next) { jsvUnLock(it->var); it->var = 0; it->charIdx = 0; return; // out of memory } // we don't ref, because StringExts are never reffed as they only have one owner (and ALWAYS have an owner) jsvSetLastChild(it->var, jsvGetRef(next)); jsvUnLock(it->var); it->var = next; it->varIndex += it->charIdx; it->charIdx = 0; // it's new, so empty } it->var->varData.str[it->charIdx] = ch; it->charsInVar = it->charIdx+1; jsvSetCharactersInVar(it->var, it->charsInVar); }
JsVar *jslNewStringFromLexer(JslCharPos *charFrom, size_t charTo) { // Original method - just copy it verbatim size_t maxLength = charTo + 1 - jsvStringIteratorGetIndex(&charFrom->it); assert(maxLength>0); // will fail if 0 // Try and create a flat string first JsVar *var = 0; if (maxLength > JSV_FLAT_STRING_BREAK_EVEN) { var = jsvNewFlatStringOfLength((unsigned int)maxLength); if (var) { // Flat string char *flatPtr = jsvGetFlatStringPointer(var); *(flatPtr++) = charFrom->currCh; JsvStringIterator it = jsvStringIteratorClone(&charFrom->it); while (jsvStringIteratorHasChar(&it) && (--maxLength>0)) { *(flatPtr++) = jsvStringIteratorGetChar(&it); jsvStringIteratorNext(&it); } jsvStringIteratorFree(&it); return var; } } // Non-flat string... var = jsvNewFromEmptyString(); if (!var) { // out of memory return 0; } //jsvAppendStringVar(var, lex->sourceVar, charFrom->it->index, (int)(charTo-charFrom)); JsVar *block = jsvLockAgain(var); block->varData.str[0] = charFrom->currCh; size_t blockChars = 1; size_t l = maxLength; // now start appending JsvStringIterator it = jsvStringIteratorClone(&charFrom->it); while (jsvStringIteratorHasChar(&it) && (--maxLength>0)) { char ch = jsvStringIteratorGetChar(&it); if (blockChars >= jsvGetMaxCharactersInVar(block)) { jsvSetCharactersInVar(block, blockChars); JsVar *next = jsvNewWithFlags(JSV_STRING_EXT_0); if (!next) break; // out of memory // we don't ref, because StringExts are never reffed as they only have one owner (and ALWAYS have an owner) jsvSetLastChild(block, jsvGetRef(next)); jsvUnLock(block); block = next; blockChars=0; // it's new, so empty } block->varData.str[blockChars++] = ch; jsvStringIteratorNext(&it); } jsvSetCharactersInVar(block, blockChars); jsvUnLock(block); // Just make sure we only assert if there's a bug here. If we just ran out of memory or at end of string it's ok assert((l == jsvGetStringLength(var)) || (jsErrorFlags&JSERR_MEMORY) || !jsvStringIteratorHasChar(&it)); jsvStringIteratorFree(&it); return var; }
/*JSON{ "type":"method", "class": "String", "name" : "substr", "generate" : "jswrap_string_substr", "params" : [ [ "start", "int", "The start character index"], [ "len", "JsVar", "The number of characters"] ], "return" : ["JsVar", "Part of this string from start for len characters"] }*/ JsVar *jswrap_string_substr(JsVar *parent, JsVarInt pStart, JsVar *vLen) { JsVar *res; JsVarInt pLen = jsvIsUndefined(vLen) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vLen); if (pLen<0) pLen=0; res = jsvNewWithFlags(JSV_STRING); if (!res) return 0; // out of memory jsvAppendStringVar(res, parent, (int)pStart, (int)pLen); return res; }
// This is for Object.keys and Object. JsVar *jswrap_object_keys_or_property_names(JsVar *obj, bool includeNonEnumerable) { // strings are iterable, but we shouldn't try and show keys for them if (jsvIsIterable(obj) && !jsvIsString(obj)) { JsvIsInternalChecker checkerFunction = jsvGetInternalFunctionCheckerFor(obj); JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (!arr) return 0; JsvIterator it; jsvIteratorNew(&it, obj); while (jsvIteratorHasElement(&it)) { JsVar *key = jsvIteratorGetKey(&it); if (!(checkerFunction && checkerFunction(key)) || (jsvIsStringEqual(key, JSPARSE_CONSTRUCTOR_VAR))) { /* Not sure why constructor is included in getOwnPropertyNames, but * not in for (i in ...) but it is, so we must explicitly override the * check in jsvIsInternalObjectKey! */ JsVar *name = jsvAsArrayIndexAndUnLock(jsvCopyNameOnly(key, false, false)); if (name) { jsvArrayPushAndUnLock(arr, name); } } jsvUnLock(key); jsvIteratorNext(&it); } jsvIteratorFree(&it); /* Search our built-in symbol table Assume that ALL builtins are non-enumerable. This isn't great but seems to work quite well right now! */ if (includeNonEnumerable) { const JswSymList *symbols = 0; JsVar *protoOwner = jspGetPrototypeOwner(obj); if (protoOwner) { symbols = jswGetSymbolListForObjectProto(protoOwner); jsvUnLock(protoOwner); } else if (!jsvIsObject(obj)) { // get symbols, but only if we're not doing it on a basic object symbols = jswGetSymbolListForObject(obj); } if (symbols) { unsigned int i; for (i=0;i<symbols->symbolCount;i++) jsvArrayAddString(arr, &symbols->symbolChars[symbols->symbols[i].strOffset]); } if (jsvIsArray(obj) || jsvIsString(obj)) { jsvArrayAddString(arr, "length"); } } return arr; } else { jsWarn("Object.keys called on non-object"); return 0; } }
static JsVar* fsGetArray(const char *name, bool create) { JsVar *arrayName = jsvFindChildFromString(execInfo.root, name, create); JsVar *arr = jsvSkipName(arrayName); if (!arr && create) { arr = jsvNewWithFlags(JSV_ARRAY); jsvSetValueOfName(arrayName, arr); } jsvUnLock(arrayName); return arr; }
/*JSON{ "type" : "constructor", "class" : "Object", "name" : "Object", "generate" : "jswrap_object_constructor", "params" : [ ["value","JsVar","A single value to be converted to an object"] ], "return" : ["JsVar","An Object"] } Creates an Object from the supplied argument */ JsVar *jswrap_object_constructor(JsVar *value) { if (jsvIsObject(value) || jsvIsArray(value) || jsvIsFunction(value)) return jsvLockAgain(value); char *objName = jswGetBasicObjectName(value); JsVar *funcName = objName ? jspGetNamedVariable(objName) : 0; if (!funcName) return jsvNewWithFlags(JSV_OBJECT); JsVar *func = jsvSkipName(funcName); JsVar *result = jspeFunctionCall(func, funcName, 0, false, 1, &value); jsvUnLock2(funcName, func); return result; }
/*JSON{ "type" : "staticmethod", "ifndef" : "SAVE_ON_FLASH", "class" : "E", "name" : "getErrorFlags", "generate" : "jswrap_espruino_getErrorFlags", "return" : ["JsVar","An array of error flags"] } Get and reset the error flags. Returns an array that can contain: `'FIFO_FULL'`: The receive FIFO filled up and data was lost. This could be state transitions for setWatch, or received characters. `'BUFFER_FULL'`: A buffer for a stream filled up and characters were lost. This can happen to any stream - Serial,HTTP,etc. `'CALLBACK'`: A callback (s`etWatch`, `setInterval`, `on('data',...)`) caused an error and so was removed. `'LOW_MEMORY'`: Memory is running low - Espruino had to run a garbage collection pass or remove some of the command history `'MEMORY'`: Espruino ran out of memory and was unable to allocate some data that it needed. */ JsVar *jswrap_espruino_getErrorFlags() { JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (!arr) return 0; if (jsErrorFlags&JSERR_RX_FIFO_FULL) jsvArrayPushAndUnLock(arr, jsvNewFromString("FIFO_FULL")); if (jsErrorFlags&JSERR_BUFFER_FULL) jsvArrayPushAndUnLock(arr, jsvNewFromString("BUFFER_FULL")); if (jsErrorFlags&JSERR_CALLBACK) jsvArrayPushAndUnLock(arr, jsvNewFromString("CALLBACK")); if (jsErrorFlags&JSERR_LOW_MEMORY) jsvArrayPushAndUnLock(arr, jsvNewFromString("LOW_MEMORY")); if (jsErrorFlags&JSERR_MEMORY) jsvArrayPushAndUnLock(arr, jsvNewFromString("MEMORY")); jsErrorFlags = JSERR_NONE; return arr; }
static JsVar *jswrap_modules_getModuleList() { JsVar *moduleListName = jsvFindChildFromString(jsiGetParser()->root, JSPARSE_MODULE_CACHE_NAME, true); if (!moduleListName) return 0; // out of memory JsVar *moduleList = jsvSkipName(moduleListName); if (!moduleList) { moduleList = jsvNewWithFlags(JSV_OBJECT); if (!moduleList) { jsvUnLock(moduleListName); return 0; } // out of memory jsvSetValueOfName(moduleListName, moduleList); // no need to unlock } jsvUnLock(moduleListName); return moduleList; }
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; }
/*JSON{ "type":"staticproperty", "class" : "process", "name" : "env", "description" : "Returns an Object containing various pre-defined variables. standard ones are BOARD, VERSION", "generate" : "jswrap_process_env", "return" : ["JsVar", "An object"] }*/ JsVar *jswrap_process_env() { JsVar *obj = jsvNewWithFlags(JSV_OBJECT); jsvUnLock(jsvObjectSetChild(obj, "VERSION", jsvNewFromString(JS_VERSION))); jsvUnLock(jsvObjectSetChild(obj, "BUILD_DATE", jsvNewFromString(__DATE__))); jsvUnLock(jsvObjectSetChild(obj, "BUILD_TIME", jsvNewFromString(__TIME__))); jsvUnLock(jsvObjectSetChild(obj, "BOARD", jsvNewFromString(PC_BOARD_ID))); jsvUnLock(jsvObjectSetChild(obj, "CHIP", jsvNewFromString(PC_BOARD_CHIP))); jsvUnLock(jsvObjectSetChild(obj, "CHIP_FAMILY", jsvNewFromString(PC_BOARD_CHIP_FAMILY))); jsvUnLock(jsvObjectSetChild(obj, "FLASH", jsvNewFromInteger(FLASH_TOTAL))); jsvUnLock(jsvObjectSetChild(obj, "RAM", jsvNewFromInteger(RAM_TOTAL))); return obj; }
JsVar *_jswrap_array_map_or_forEach(JsVar *parent, JsVar *funcVar, JsVar *thisVar, bool isMap) { const char *name = isMap ? "map":"forEach"; if (!jsvIsIterable(parent)) { jsError("Array.%s can only be called on something iterable", name); return 0; } if (!jsvIsFunction(funcVar)) { jsError("Array.%s's first argument should be a function", name); return 0; } if (!jsvIsUndefined(thisVar) && !jsvIsObject(thisVar)) { jsError("Array.%s's second argument should be undefined, or an object", name); return 0; } JsVar *array = 0; if (isMap) array = jsvNewWithFlags(JSV_ARRAY); if (array || !isMap) { JsvIterator it; jsvIteratorNew(&it, parent); while (jsvIteratorHasElement(&it)) { JsVar *index = jsvIteratorGetKey(&it); if (jsvIsInt(index)) { JsVarInt idxValue = jsvGetInteger(index); JsVar *args[3], *mapped; args[0] = jsvIteratorGetValue(&it); args[1] = jsvNewFromInteger(idxValue); // child is a variable name, create a new variable for the index args[2] = parent; mapped = jspeFunctionCall(funcVar, 0, thisVar, false, 3, args); jsvUnLock(args[0]); jsvUnLock(args[1]); if (mapped) { if (isMap) { JsVar *name = jsvNewFromInteger(idxValue); if (name) { // out of memory? jsvMakeIntoVariableName(name, mapped); jsvAddName(array, name); jsvUnLock(name); } } jsvUnLock(mapped); } } jsvUnLock(index); jsvIteratorNext(&it); } jsvIteratorFree(&it); } return array; }
/*JSON{ "type" : "method", "class" : "Array", "name" : "shift", "ifndef" : "SAVE_ON_FLASH", "generate" : "jswrap_array_shift", "params" : [ ], "return" : ["JsVar","The element that was removed"] } Remove the first element of the array, and return it */ JsVar *jswrap_array_shift(JsVar *parent) { // just use splice, as this does all the hard work for us JsVar *nRemove = jsvNewFromInteger(1); JsVar *elements = jsvNewWithFlags(JSV_ARRAY); JsVar *arr = jswrap_array_splice(parent, 0, nRemove, elements); jsvUnLock(elements); jsvUnLock(nRemove); // unpack element from the array JsVar *el = 0; if (jsvIsArray(arr)) el = jsvArrayPop(arr); jsvUnLock(arr); return el; }
/*JSON{ "type" : "staticmethod", "class" : "Object", "name" : "create", "generate" : "jswrap_object_create", "params" : [ ["proto","JsVar","A prototype object","propertiesObject","JsVar","An object containing properties. NOT IMPLEMENTED"] ], "return" : ["JsVar","A new object"] } Creates a new object with the specified prototype object and properties. properties are currently unsupported. */ JsVar *jswrap_object_create(JsVar *proto, JsVar *propertiesObject) { if (!jsvIsObject(proto) && !jsvIsNull(proto)) { jsWarn("Object prototype may only be an Object or null: %t", proto); return 0; } if (jsvIsObject(propertiesObject)) { jsWarn("propertiesObject is not supported yet"); } JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (!obj) return 0; if (jsvIsObject(proto)) jsvObjectSetChild(obj, JSPARSE_INHERITS_VAR, proto); return obj; }
/*JSON{ "type":"method", "class": "String", "name" : "substring", "generate" : "jswrap_string_substring", "params" : [ [ "start", "int", "The start character index"], [ "end", "JsVar", "The end character index"] ], "return" : ["JsVar", "The part of this string between start and end"] }*/ JsVar *jswrap_string_substring(JsVar *parent, JsVarInt pStart, JsVar *vEnd) { JsVar *res; JsVarInt pEnd = jsvIsUndefined(vEnd) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vEnd); if (pStart<0) pStart=0; if (pEnd<0) pEnd=0; if (pEnd<pStart) { JsVarInt l = pStart; pStart = pEnd; pEnd = l; } res = jsvNewWithFlags(JSV_STRING); if (!res) return 0; // out of memory jsvAppendStringVar(res, parent, (int)pStart, (int)(pEnd-pStart)); return res; }