Ejemplo n.º 1
0
/*JSON{ "type":"method", "class": "Function", "name" : "apply",
         "description" : ["This executes the function with the supplied 'this' argument and parameters"],
         "generate" : "jswrap_function_apply",
         "params" : [ [ "this", "JsVar", "The value to use as the 'this' argument when executing the function"],
                      [ "args", "JsVar", "Optional Array of Aruments"]
                    ],
         "return" : [ "JsVar", "The return value of executing this function" ]
}*/
JsVar *jswrap_function_apply(JsVar *parent, JsVar *thisArg, JsVar *argsArray) {
  unsigned int i;
  JsVar **args = 0;
  size_t argC = 0;

  if (jsvIsArray(argsArray)) {
    argC = (size_t)jsvGetArrayLength(argsArray);
    if (argC>64) argC=64; // sanity
    args = (JsVar**)alloca((size_t)argC * sizeof(JsVar*));


    for (i=0;i<argC;i++) args[i] = 0;
    JsvArrayIterator it;
    jsvArrayIteratorNew(&it, argsArray);
    while (jsvArrayIteratorHasElement(&it)) {
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvArrayIteratorGetIndex(&it));
      if (idx>=0 && idx<(int)argC) {
        assert(!args[idx]); // just in case there were dups
        args[idx] = jsvArrayIteratorGetElement(&it);
      }
      jsvArrayIteratorNext(&it);
    }
    jsvArrayIteratorFree(&it);
  } else if (!jsvIsUndefined(argsArray)) {
    jsWarn("Second argument to Function.apply must be an array");
  }

  JsVar *r = jspeFunctionCall(parent, 0, thisArg, false, (int)argC, args);
  for (i=0;i<argC;i++) jsvUnLock(args[i]);
  return r;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
/*JSON{ "type":"method", "class": "Array", "name" : "splice",
         "description" : "Both remove and add items to an array",
         "generate" : "jswrap_array_splice",
         "params" : [ [ "index", "int", "Index at which to start changing the array. If negative, will begin that many elements from the end"],
                      [ "howMany", "JsVar", "An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed."],
                      [ "element1", "JsVar", "A new item to add (optional)" ],
                      [ "element2", "JsVar", "A new item to add (optional)" ],
                      [ "element3", "JsVar", "A new item to add (optional)" ],
                      [ "element4", "JsVar", "A new item to add (optional)" ],
                      [ "element5", "JsVar", "A new item to add (optional)" ],
                      [ "element6", "JsVar", "A new item to add (optional)" ] ],
         "return" : ["JsVar", "An array containing the removed elements. If only one element is removed, an array of one element is returned."]
}*/
JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *element1, JsVar *element2, JsVar *element3, JsVar *element4, JsVar *element5, JsVar *element6) {
  JsVarInt len = jsvGetArrayLength(parent);
  if (index<0) index+=len;
  if (index<0) index=0;
  if (index>len) index=len;
  JsVarInt howMany = len; // how many to delete!
  if (jsvIsInt(howManyVar)) howMany = jsvGetInteger(howManyVar);
  if (howMany > len-index) howMany = len-index;
  JsVarInt newItems = 0;
  if (element1) newItems++;
  if (element2) newItems++;
  if (element3) newItems++;
  if (element4) newItems++;
  if (element5) newItems++;
  if (element6) newItems++;
  JsVarInt shift = newItems-howMany;

  bool needToAdd = false;
  JsVar *result = jsvNewWithFlags(JSV_ARRAY);

  JsArrayIterator it;
  jsvArrayIteratorNew(&it, parent);
  while (jsvArrayIteratorHasElement(&it) && !needToAdd) {
    bool goToNext = true;
    JsVar *idxVar = jsvArrayIteratorGetIndex(&it);
    if (idxVar && jsvIsInt(idxVar)) {
      JsVarInt idx = jsvGetInteger(idxVar);
      if (idx<index) {
        // do nothing...
      } else if (idx<index+howMany) { // must delete
        if (result) { // append to result array
          JsVar *el = jsvArrayIteratorGetElement(&it);
          jsvArrayPush(result, el);
          jsvUnLock(el);
        }
        // delete
        goToNext = false;
        JsVar *toRemove = jsvArrayIteratorGetIndex(&it);
        jsvArrayIteratorNext(&it);
        jsvRemoveChild(parent, toRemove);
        jsvUnLock(toRemove);
      } else { // we're greater than the amount we need to remove now
        needToAdd = true;
        goToNext = false;
      }
    }
    jsvUnLock(idxVar);
    if (goToNext) jsvArrayIteratorNext(&it);
  }
  // now we add everything
  JsVar *beforeIndex = jsvArrayIteratorGetIndex(&it);
  if (element1) jsvArrayInsertBefore(parent, beforeIndex, element1);
  if (element2) jsvArrayInsertBefore(parent, beforeIndex, element2);
  if (element3) jsvArrayInsertBefore(parent, beforeIndex, element3);
  if (element4) jsvArrayInsertBefore(parent, beforeIndex, element4);
  if (element5) jsvArrayInsertBefore(parent, beforeIndex, element5);
  if (element6) jsvArrayInsertBefore(parent, beforeIndex, element6);
  jsvUnLock(beforeIndex);
  // And finally renumber
  while (jsvArrayIteratorHasElement(&it)) {
      JsVar *idxVar = jsvArrayIteratorGetIndex(&it);
      if (idxVar && jsvIsInt(idxVar)) {
        jsvSetInteger(idxVar, jsvGetInteger(idxVar)+shift);
      }
      jsvUnLock(idxVar);
      jsvArrayIteratorNext(&it);
    }
  // free
  jsvArrayIteratorFree(&it);

  return result;
}
Ejemplo n.º 4
0
void httpClientConnectionsIdle() {
  char buf[64];

  JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_CLIENT_CONNECTIONS,false);
  if (!arr) return;

  JsArrayIterator it;
  jsvArrayIteratorNew(&it, arr);
  while (jsvArrayIteratorHasElement(&it)) {
    JsVar *connection = jsvArrayIteratorGetElement(&it);
    bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
    SOCKET sckt = (SOCKET)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
    bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
    JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);

    /* We do this up here because we want to wait until we have been once
     * around the idle loop (=callbacks have been executed) before we run this */
    if (hadHeaders && receiveData) {
      JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
      jsiQueueObjectCallbacks(resVar, HTTP_NAME_ON_DATA, receiveData, 0);
      jsvUnLock(resVar);
      // clear - because we have issued a callback
      jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
    }

    if (sckt!=INVALID_SOCKET) {
      JsVar *sendData = jsvObjectGetChild(connection,HTTP_NAME_SEND_DATA,0);
      // send data if possible
      if (sendData) {
        // this will wait to see if we can write any more, but ALSO
        // will wait for connection
        fd_set writefds;
        FD_ZERO(&writefds);
        FD_SET(sckt, &writefds);
        struct timeval time;
        time.tv_sec = 0;
        time.tv_usec = 0;
        int n = select(sckt+1, 0, &writefds, 0, &time);
        if (n==SOCKET_ERROR ) {
           // we probably disconnected so just get rid of this
          closeConnectionNow = true;
        } else if (FD_ISSET(sckt, &writefds)) {
          if (!_http_send(sckt, &sendData))
            closeConnectionNow = true;
          jsvObjectSetChild(connection, HTTP_NAME_SEND_DATA, sendData); // _http_send prob updated sendData
        }
#ifdef USE_CC3000
      } else { // When in CC3000, write then read (FIXME)
#else
      } // When in Linux, just read and write at the same time
      {
#endif
        // Now receive data
        fd_set s;
        FD_ZERO(&s);
        FD_SET(sckt,&s);
        // check for waiting clients
        struct timeval timeout;
        timeout.tv_sec = 0;
  #ifdef USE_CC3000
        timeout.tv_usec = 5000; // 5 millisec
  #else
        timeout.tv_usec = 0;
  #endif
        int n = select(sckt+1,&s,NULL,NULL,&timeout);
        if (n==SOCKET_ERROR) {
          // we probably disconnected so just get rid of this
          closeConnectionNow = true;
        } else if (n>0) {
          // receive data
          int num = (int)recv(sckt,buf,sizeof(buf),0);
          // add it to our request string
          if (num>0) {
            if (!receiveData) {
              receiveData = jsvNewFromEmptyString();
              jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
            }
            if (receiveData) { // could be out of memory
              jsvAppendStringBuf(receiveData, buf, num);
              if (!hadHeaders) {
                JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
                if (httpParseHeaders(&receiveData, resVar, false)) {
                  hadHeaders = true;
                  jsvUnLock(jsvObjectSetChild(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders)));
                  jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_CONNECT, resVar, 0);
                }
                jsvUnLock(resVar);
                jsvObjectSetChild(connection, HTTP_NAME_RECEIVE_DATA, receiveData);
              }
            }
          } else if (num==0) {
            // select says data, but recv says 0 means connection is closed
            closeConnectionNow = true;
          }
        } else {
  #ifdef USE_CC3000
          // Nothing to send or receive, and closed
          if (!sendData && cc3000_socket_has_closed(sckt))
            closeConnectionNow = true;
  #endif
        }
      }
      jsvUnLock(sendData);
    }
    jsvUnLock(receiveData);
    if (closeConnectionNow) {
      JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
      jsiQueueObjectCallbacks(resVar, HTTP_NAME_ON_CLOSE, 0, 0);
      jsvUnLock(resVar);

      _httpClientConnectionKill(connection);
      JsVar *connectionName = jsvArrayIteratorGetIndex(&it);
      jsvArrayIteratorNext(&it);
      jsvRemoveChild(arr, connectionName);
      jsvUnLock(connectionName);
    } else
      jsvArrayIteratorNext(&it);
    jsvUnLock(connection);
  }
  jsvUnLock(arr);
}
Ejemplo n.º 5
0
void httpServerConnectionsIdle() {
  char buf[64];

  JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS,false);
  if (!arr) return;
  JsArrayIterator it;
  jsvArrayIteratorNew(&it, arr);
  while (jsvArrayIteratorHasElement(&it)) {
    JsVar *connection = jsvArrayIteratorGetElement(&it);
    JsVar *connectReponse = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
    SOCKET sckt = (SOCKET)jsvGetIntegerAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined
    bool closeConnectionNow = jsvGetBoolAndUnLock(jsvObjectGetChild(connection, HTTP_NAME_CLOSENOW, false));
    bool hadData = false;
    // TODO: look for unreffed connections?
    fd_set s;
    FD_ZERO(&s);
    FD_SET(sckt,&s);
    // check for waiting clients
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    int n = select(sckt+1,&s,NULL,NULL,&timeout);
    if (n==SOCKET_ERROR) {
      // we probably disconnected so just get rid of this
      closeConnectionNow = true;
    } else if (n>0) {
      hadData = true;
      // receive data
      int num = (int)recv(sckt,buf,sizeof(buf),0);
      // add it to our request string
      if (num>0) {
        JsVar *receiveData = jsvObjectGetChild(connection,HTTP_NAME_RECEIVE_DATA,0);
        if (!receiveData) {
          receiveData = jsvNewFromEmptyString();
          jsvObjectSetChild(connection,HTTP_NAME_RECEIVE_DATA,receiveData);
        }
        if (receiveData) {
          jsvAppendStringBuf(receiveData, buf, num);
          bool hadHeaders = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_HAD_HEADERS,0));
          if (!hadHeaders && httpParseHeaders(&receiveData, connection, true)) {
            hadHeaders = true;
            jsvUnLock(jsvObjectSetChild(connection, HTTP_NAME_HAD_HEADERS, jsvNewFromBool(hadHeaders)));
            JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
            JsVar *server = jsvObjectGetChild(connection,HTTP_NAME_SERVER_VAR,0);
            jsiQueueObjectCallbacks(server, HTTP_NAME_ON_CONNECT, connection, resVar);
            jsvUnLock(server);
            jsvUnLock(resVar);
          }
          jsvUnLock(receiveData);
        }
      }
    }

    // send data if possible
    JsVar *sendData = jsvObjectGetChild(connectReponse,HTTP_NAME_SEND_DATA,0);
    if (sendData) {
      fd_set writefds;
      FD_ZERO(&writefds);
      FD_SET(sckt, &writefds);
      struct timeval time;
      time.tv_sec = 0;
      time.tv_usec = 0;
      int n = select(sckt+1, 0, &writefds, 0, &time);
      if (n==SOCKET_ERROR ) {
         // we probably disconnected so just get rid of this
        closeConnectionNow = true;
      } else if (FD_ISSET(sckt, &writefds)) {
        if (!_http_send(sckt, &sendData))
          closeConnectionNow = true;
      }
      jsvObjectSetChild(connectReponse, HTTP_NAME_SEND_DATA, sendData); // _http_send prob updated sendData
    } else {
#ifdef USE_CC3000
      // nothing to send, nothing to receive, and closed...
      if (!hadData && cc3000_socket_has_closed(sckt))
        closeConnectionNow = true;
#endif
    }
    if (jsvGetBoolAndUnLock(jsvObjectGetChild(connectReponse,HTTP_NAME_CLOSE,0)) && !sendData)
      closeConnectionNow = true;
    jsvUnLock(sendData);
    if (closeConnectionNow) {
      JsVar *resVar = jsvObjectGetChild(connection,HTTP_NAME_RESPONSE_VAR,0);
      jsiQueueObjectCallbacks(resVar, HTTP_NAME_ON_CLOSE, 0, 0);
      jsvUnLock(resVar);

      _httpServerConnectionKill(connection);
      JsVar *connectionName = jsvArrayIteratorGetIndex(&it);
      jsvArrayIteratorNext(&it);
      jsvRemoveChild(arr, connectionName);
      jsvUnLock(connectionName);
    } else
      jsvArrayIteratorNext(&it);
    jsvUnLock(connection);
    jsvUnLock(connectReponse);
  }
  jsvArrayIteratorFree(&it);
  jsvUnLock(arr);
}