Пример #1
0
void serverResponseWrite(JsVar *httpServerResponseVar, JsVar *data) {
    // Append data to sendData
    JsVar *sendData = jsvObjectGetChild(httpServerResponseVar, HTTP_NAME_SEND_DATA, 0);
    if (!sendData) {
        // no sendData, so no headers - add them!
        JsVar *sendHeaders = jsvObjectGetChild(httpServerResponseVar, HTTP_NAME_HEADERS, 0);
        if (sendHeaders) {
            sendData = jsvVarPrintf("HTTP/1.0 %d OK\r\nServer: Espruino "JS_VERSION"\r\n", jsvGetIntegerAndUnLock(jsvObjectGetChild(httpServerResponseVar, HTTP_NAME_CODE, 0)));
            httpAppendHeaders(sendData, sendHeaders);
            jsvObjectSetChild(httpServerResponseVar, HTTP_NAME_HEADERS, 0);
            jsvUnLock(sendHeaders);
            // finally add ending newline
            jsvAppendString(sendData, "\r\n");
        } else if (!jsvIsUndefined(data)) {
            // we have already sent headers, but want to send more
            sendData = jsvNewFromEmptyString();
        }
        jsvObjectSetChild(httpServerResponseVar, HTTP_NAME_SEND_DATA, sendData);
    }
    if (sendData && !jsvIsUndefined(data)) {
        JsVar *s = jsvAsString(data, false);
        if (s) jsvAppendStringVarComplete(sendData,s);
        jsvUnLock(s);
    }
    jsvUnLock(sendData);
}
Пример #2
0
/*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;
}
Пример #3
0
/*JSON{
  "type" : "staticmethod",
  "class" : "crypto",
  "name" : "PBKDF2",
  "generate" : "jswrap_crypto_PBKDF2",
  "params" : [
    ["passphrase","JsVar","Passphrase"],
    ["salt","JsVar","Salt for turning passphrase into a key"],
    ["options","JsVar","Object of Options, `{ keySize: 8 (in 32 bit words), iterations: 10, hasher: 'SHA1'/'SHA224'/'SHA256'/'SHA384'/'SHA512' }`"]
  ],
  "return" : ["JsVar","Returns an ArrayBuffer"],
  "return_object" : "ArrayBuffer",
  "ifdef" : "USE_TLS"
}

Password-Based Key Derivation Function 2 algorithm, using SHA512
*/
JsVar *jswrap_crypto_PBKDF2(JsVar *passphrase, JsVar *salt, JsVar *options) {
  int iterations = 1;
  int keySize = 128/32;
  mbedtls_md_type_t hasher = MBEDTLS_MD_SHA1;


  if (jsvIsObject(options)) {
    keySize = jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "keySize", 0));
    if (keySize<=0) keySize=128/32;
    iterations = jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "iterations", 0));
    if (iterations<1) iterations = 1;

    JsVar *hashVar = jsvObjectGetChild(options, "hasher", 0);
    if (!jsvIsUndefined(hashVar))
      hasher = jswrap_crypto_getHasher(hashVar);
    jsvUnLock(hashVar);

  } else if (!jsvIsUndefined(options))
    jsError("Options should be an object or undefined, got %t", options);

  if (hasher == MBEDTLS_MD_NONE)
    return 0; // already shown an error

  JSV_GET_AS_CHAR_ARRAY(passPtr, passLen, passphrase);
  if (!passPtr) return 0;
  JSV_GET_AS_CHAR_ARRAY(saltPtr, saltLen, salt);
  if (!saltPtr) return 0;

  int err;
  mbedtls_md_context_t ctx;

  mbedtls_md_init( &ctx );
  err = mbedtls_md_setup( &ctx, mbedtls_md_info_from_type( hasher ), 1 );
  assert(err==0);

  char *keyPtr = 0;
  JsVar *keyArr = jsvNewArrayBufferWithPtr((unsigned)keySize*4, &keyPtr);
  if (!keyPtr) {
    jsError("Not enough memory for result");
    return 0;
  }

  err = mbedtls_pkcs5_pbkdf2_hmac( &ctx,
        (unsigned char*)passPtr, passLen,
        (unsigned char*)saltPtr, saltLen,
        (unsigned)iterations,
        (unsigned)keySize*4, (unsigned char*)keyPtr );
  mbedtls_md_free( &ctx );
  if (!err) {
    return keyArr;
  } else {
    jswrap_crypto_error(err);
    jsvUnLock(keyArr);
    return 0;
  }
}
Пример #4
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Trig",
  "name" : "setup",
  "generate" : "jswrap_trig_setup",
  "params" : [
    ["pin","pin","The pin to use for triggering"],
    ["options","JsVar","Additional options as an object. defaults are: ```{teethTotal:60,teethMissing:2,minRPM:30,keyPosition:0}```"]
  ]
}
Initialise the trigger class
*/
void jswrap_trig_setup(Pin pin, JsVar *options) {
  if (!jshIsPinValid(pin)) {
    jsError("Invalid pin supplied as an argument to Trig.setup");
    return;
  }

  TriggerStruct *trig = &mainTrigger;
  // static info
  trig->teethMissing = 2;
  trig->teethTotal = 60;
  trig->keyPosition = 0;
  JsVarFloat minRPM = 30;
  if (jsvIsObject(options)) {
    JsVar *v;
    v = jsvObjectGetChild(options, "teethMissing", 0);
    if (!jsvIsUndefined(v)) trig->teethMissing = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    v = jsvObjectGetChild(options, "teethTotal", 0);
    if (!jsvIsUndefined(v)) trig->teethTotal = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    v = jsvObjectGetChild(options, "minRPM", 0);
    if (!jsvIsUndefined(v)) minRPM = jsvGetFloat(v);
    jsvUnLock(v);
    v = jsvObjectGetChild(options, "keyPosition", 0);
    if (!jsvIsUndefined(v)) trig->keyPosition = jsvGetFloat(v);
    jsvUnLock(v);
  }
  trig->maxTooth = (unsigned int)jshGetTimeFromMilliseconds(60000 / (JsVarFloat)(trig->teethTotal * minRPM));

  // semi-static info
  int i;
  for (i=0;i<TRIGGER_TRIGGERS_COUNT;i++) {
    trig->triggers[i].tooth = TRIGGERPOINT_TOOTH_DISABLE;
    trig->triggers[i].newTooth = TRIGGERPOINT_TOOTH_DISABLE;
  }
  // dynamic info
  trig->lastTime = jshGetSystemTime();
  trig->avrTrigger = (unsigned int)jshGetTimeFromMilliseconds(10); // average time for a trigger pulse
  trig->avrTooth = (unsigned int)jshGetTimeFromMilliseconds(10); // average time for a tooth
  trig->currTooth = 0;
  trig->teethSinceStart = 0;
  trig->wrongTriggerTeeth = 0;
  // finally set up the watch!
  if (jshIsPinValid(trig->sensorPin))
    jshPinWatch(trig->sensorPin, false);
  trig->sensorPin = pin;
  jshPinWatch(trig->sensorPin, true);
}
Пример #5
0
/*JSON{
  "type" : "constructor",
  "class" : "Number",
  "name" : "Number",
  "generate" : "jswrap_number_constructor",
  "params" : [
    ["value","JsVarArray","A single value to be converted to a number"]
  ],
  "return" : ["JsVar","A Number object"]
}
Creates a number
 */
JsVar *jswrap_number_constructor(JsVar *args) {
  if (jsvGetArrayLength(args)==0) return jsvNewFromInteger(0);
  JsVar *val = jsvGetArrayItem(args, 0);
  JsVar *result = 0;

  if (jsvIsArray(val)) {
    JsVarInt l = jsvGetArrayLength(val);
    if (l==0) result = jsvNewFromInteger(0);
    else if (l==1) {
      JsVar *n = jsvGetArrayItem(val, 0);
      if (jsvIsString(n) && jsvIsEmptyString(n)) result = jsvNewFromInteger(0);
      else if (!jsvIsBoolean(n)) result=jsvAsNumber(n);
      jsvUnLock(n);
    } // else NaN
  } else if (jsvIsUndefined(val) || jsvIsObject(val))
    result = 0;
  else {
    if (jsvIsString(val) && jsvIsEmptyString(val)) {
      result = jsvNewFromInteger(0);
    } else
      result = jsvAsNumber(val);
  }
  jsvUnLock(val);
  if (result) return result;
  return jsvNewFromFloat(NAN);
}
Пример #6
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;
}
Пример #7
0
/*JSON{
  "type" : "function",
  "name" : "trace",
  "ifndef" : "SAVE_ON_FLASH",
  "generate" : "jswrap_interface_trace",
  "params" : [
    ["root","JsVar","The symbol to output (optional). If nothing is specified, everything will be output"]
  ]
}
Output debugging information
 */
void jswrap_interface_trace(JsVar *root) {
  if (jsvIsUndefined(root)) {
    jsvTrace(execInfo.root, 0);
  } else {
    jsvTrace(root, 0);
  }
}
Пример #8
0
/*JSON{
  "type" : "function",
  "name" : "clearTimeout",
  "generate" : "jswrap_interface_clearTimeout",
  "params" : [
    ["id","JsVar","The id returned by a previous call to setTimeout"]
  ]
}
Clear the Timeout that was created with setTimeout, for example:

```var id = setTimeout(function () { print('foo'); }, 1000);```

```clearTimeout(id);```

If no argument is supplied, all timers and intervals are stopped
 */
void _jswrap_interface_clearTimeoutOrInterval(JsVar *idVar, bool isTimeout) {
  JsVar *timerArrayPtr = jsvLock(timerArray);
  if (jsvIsUndefined(idVar)) {
    /* Delete all timers EXCEPT those with a 'watch' field,
     as those were generated by jsinteractive.c for debouncing watches */
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, timerArrayPtr);
    while (jsvObjectIteratorHasValue(&it)) {
      JsVar *timerPtr = jsvObjectIteratorGetValue(&it);
      JsVar *watchPtr = jsvObjectGetChild(timerPtr, "watch", 0);
      if (!watchPtr)
        jsvObjectIteratorRemoveAndGotoNext(&it, timerArrayPtr);
      else
        jsvObjectIteratorNext(&it); 
      jsvUnLock2(watchPtr, timerPtr);
    }
    jsvObjectIteratorFree(&it);
  } else {
    JsVar *child = jsvIsBasic(idVar) ? jsvFindChildFromVar(timerArrayPtr, idVar, false) : 0;
    if (child) {
      JsVar *timerArrayPtr = jsvLock(timerArray);
      jsvRemoveChild(timerArrayPtr, child);
      jsvUnLock2(child, timerArrayPtr);
    } else {
      if (isTimeout)
        jsExceptionHere(JSET_ERROR, "Unknown Timeout");
      else
        jsExceptionHere(JSET_ERROR, "Unknown Interval");
    }
  }
  jsvUnLock(timerArrayPtr);
  jsiTimersChanged(); // mark timers as changed
}
Пример #9
0
/*JSON{ "type":"method", "class": "Serial", "name" : "setup",
         "description" : ["Setup this Serial port with the given baud rate and options.",
                          "If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)"],
         "generate" : "jswrap_serial_setup",
         "params" : [ [ "baudrate", "JsVar", "The baud rate - the default is 9600"],
                      [ "options", "JsVar", ["An optional structure containing extra information on initialising the serial port.",
                                             "```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1}```",
                                             "You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.",
                                             "Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite" ] ] ]
}*/
void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_USART(device)) return;

  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (!jsvIsUndefined(baud)) {
    int b = (int)jsvGetInteger(baud);
    if (b<=100 || b > 10000000)
      jsExceptionHere(JSET_ERROR, "Invalid baud rate specified");
    else
      inf.baudRate = b;
  }


  if (jsvIsObject(options)) {
    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));    

    JsVar *v;
    v = jsvObjectGetChild(options, "bytesize", 0);
    if (jsvIsInt(v)) 
      inf.bytesize = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    
    inf.parity = 0;
    v = jsvObjectGetChild(options, "parity", 0);
    if(jsvIsString(v)) {
      if(jsvIsStringEqual(v, "o") || jsvIsStringEqual(v, "odd"))
        inf.parity = 1;
      else if(jsvIsStringEqual(v, "e") || jsvIsStringEqual(v, "even"))
        inf.parity = 2;
    } else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }
    jsvUnLock(v);
    if (inf.parity>2) {
      jsExceptionHere(JSET_ERROR, "Invalid parity %d", inf.parity);
      return;
    }

    v = jsvObjectGetChild(options, "stopbits", 0);
    if (jsvIsInt(v)) 
      inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  if (inf.baudRate != DEFAULT_BAUD_RATE) {
    jsvUnLock(jsvObjectSetChild(parent, USART_BAUDRATE_NAME, jsvNewFromInteger(inf.baudRate)));
  } else
    jsvRemoveNamedChild(parent, USART_BAUDRATE_NAME);
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
/*JSON{ "type":"function", "name" : "trace", "ifndef" : "SAVE_ON_FLASH",
         "description" : "Output debugging information",
         "generate" : "jswrap_interface_trace",
         "params" : [ [ "root", "JsVarName", "The symbol to output (optional). If nothing is specified, everything will be output"] ]
}*/
void jswrap_interface_trace(JsVar *root) {
  if (jsvIsUndefined(root)) {
    jsvTrace(jsvGetRef(jsiGetParser()->root), 0);
  } else {
    jsvTrace(jsvGetRef(root), 0);
  }
}
Пример #11
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "removeAllListeners",
  "generate" : "jswrap_object_removeAllListeners",
  "params" : [
    ["event","JsVar","The name of the event, for instance 'data'"]
  ]
}
Removes all listeners, or those of the specified event.
 */
void jswrap_object_removeAllListeners(JsVar *parent, JsVar *event) {
  if (!jsvHasChildren(parent)) {
    jsWarn("Parent must be an object - not a String, Integer, etc.");
    return;
  }
  if (jsvIsString(event)) {
    // remove the whole child containing listeners
    JsVar *eventName = jsvVarPrintf(JS_EVENT_PREFIX"%s",event);
    if (!eventName) return; // no memory

    JsVar *eventList = jsvFindChildFromVar(parent, eventName, true);
    jsvUnLock(eventName);
    if (eventList) {
      jsvRemoveChild(parent, eventList);
      jsvUnLock(eventList);
    }
  } else if (jsvIsUndefined(event)) {
    // Eep. We must remove everything beginning with '#on' (JS_EVENT_PREFIX)
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, parent);
    while (jsvObjectIteratorHasValue(&it)) {
      JsVar *key = jsvObjectIteratorGetKey(&it);
      jsvObjectIteratorNext(&it);
      if (jsvIsStringEqualOrStartsWith(key, JS_EVENT_PREFIX, true)) {
        // begins with #on - we must kill it
        jsvRemoveChild(parent, key);
      }
      jsvUnLock(key);
    }
    jsvObjectIteratorFree(&it);
  } else {
    jsWarn("First argument to EventEmitter.removeAllListeners(..) must be a string, or undefined");
    return;
  }
}
Пример #12
0
/*JSON{
  "type" : "method",
  "class" : "Function",
  "name" : "apply",
  "generate" : "jswrap_function_apply_or_call",
  "params" : [
    ["this","JsVar","The value to use as the 'this' argument when executing the function"],
    ["args","JsVar","Optional Array of Arguments"]
  ],
  "return" : ["JsVar","The return value of executing this function"]
}
This executes the function with the supplied 'this' argument and parameters
 */
JsVar *jswrap_function_apply_or_call(JsVar *parent, JsVar *thisArg, JsVar *argsArray) {
  unsigned int i;
  JsVar **args = 0;
  unsigned int argC = 0;

  if (jsvIsIterable(argsArray)) {
    argC = (unsigned int)jsvGetLength(argsArray);
    if (argC>64) {
      jsExceptionHere(JSET_ERROR, "Array passed to Function.apply is too big! Maximum 64 arguments, got %d", argC);
      return 0;
    }
    args = (JsVar**)alloca((size_t)argC * sizeof(JsVar*));
    for (i=0;i<argC;i++) args[i] = 0;
    // TODO: Use jsvGetArrayItems?
    JsvIterator it;
    jsvIteratorNew(&it, argsArray);
    while (jsvIteratorHasElement(&it)) {
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvIteratorGetKey(&it));
      if (idx>=0 && idx<(int)argC) {
        assert(!args[idx]); // just in case there were dups
        args[idx] = jsvIteratorGetValue(&it);
      }
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
  } else if (!jsvIsUndefined(argsArray)) {
    jsExceptionHere(JSET_ERROR, "Second argument to Function.apply must be iterable, got %t", argsArray);
    return 0;
  }

  JsVar *r = jspeFunctionCall(parent, 0, thisArg, false, (int)argC, args);
  jsvUnLockMany(argC, args);
  return r;
}
Пример #13
0
/*JSON{
    "type" : "staticmethod",
    "class" : "NRF",
    "name" : "setAdvertising",
    "generate" : "jswrap_nrf_bluetooth_setAdvertising",
    "params" : [
      ["data","JsVar","The data to advertise as an object - see below for more info"]
    ]
}

Data is of the form `{ UUID : data_as_byte_array }`. For example to return battery level at 95%, do:

```
NRF.setAdvertising({
  0x180F : [95]
});
```

Or you could report the current temperature:

```
setInterval(function() {
  NRF.setAdvertising({
    0x1809 : [0|E.getTemperature()]
  });
}, 30000);
```
*/
void jswrap_nrf_bluetooth_setAdvertising(JsVar *data) {
  uint32_t err_code;
  ble_advdata_t advdata;
  setup_advdata(&advdata);

  if (jsvIsObject(data)) {
    ble_advdata_service_data_t *service_data = (ble_advdata_service_data_t*)alloca(jsvGetChildren(data)*sizeof(ble_advdata_service_data_t));
    int n = 0;
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, data);
    while (jsvObjectIteratorHasValue(&it)) {
      service_data[n].service_uuid = jsvGetIntegerAndUnLock(jsvObjectIteratorGetKey(&it));
      JsVar *v = jsvObjectIteratorGetValue(&it);
      JSV_GET_AS_CHAR_ARRAY(dPtr, dLen, v);
      jsvUnLock(v);
      service_data[n].data.size    = dLen;
      service_data[n].data.p_data  = dPtr;
      jsvObjectIteratorNext(&it);
      n++;
    }
    jsvObjectIteratorFree(&it);

    advdata.service_data_count   = n;
    advdata.p_service_data_array = service_data;
  } else if (!jsvIsUndefined(data)) {
    jsExceptionHere(JSET_TYPEERROR, "Expecting object or undefined, got %t", data);
  }

  err_code = ble_advdata_set(&advdata, NULL);
  if (err_code)
    jsExceptionHere(JSET_ERROR, "Got BLE error code %d", err_code);
}
Пример #14
0
/*JSON{
  "type" : "method",
  "class" : "Socket",
  "name" : "end",
  "generate" : "jswrap_net_socket_end",
  "params" : [
    ["data","JsVar","A string containing data to send"]
  ]
}
Close this socket - optional data to append as an argument
*/
void jswrap_net_socket_end(JsVar *parent, JsVar *data) {
  JsNetwork net;
  if (!networkGetFromVarIfOnline(&net)) return;

  if (!jsvIsUndefined(data)) jswrap_net_socket_write(parent, data);
  clientRequestEnd(&net, parent);
  networkFree(&net);
}
Пример #15
0
/*JSON{
  "type" : "staticmethod",
  "class" : "fs",
  "name" : "pipe",
  "ifndef" : "SAVE_ON_FLASH",
  "generate" : "jswrap_pipe",
  "params" : [
    ["source","JsVar","The source file/stream that will send content."],
    ["destination","JsVar","The destination file/stream that will receive content from the source."],
    ["options","JsVar",["An optional object `{ chunkSize : int=64, end : bool=true, complete : function }`","chunkSize : The amount of data to pipe from source to destination at a time","complete : a function to call when the pipe activity is complete","end : call the 'end' function on the destination when the source is finished"]]
  ]
}*/
void jswrap_pipe(JsVar* source, JsVar* dest, JsVar* options) {
  if (!source || !dest) return;
  JsVar *pipe = jspNewObject(0, "Pipe");
  JsVar *arr = pipeGetArray(true);
  JsVar* position = jsvNewFromInteger(0);
  if (pipe && arr && position) {// out of memory?
    JsVar *readFunc = jspGetNamedField(source, "read", false);
    JsVar *writeFunc = jspGetNamedField(dest, "write", false);
    if(jsvIsFunction(readFunc)) {
      if(jsvIsFunction(writeFunc)) {
        JsVarInt chunkSize = 64;
        bool callEnd = true;
        // parse Options Object
        if (jsvIsObject(options)) {
          JsVar *c;
          c = jsvObjectGetChild(options, "complete", false);
          if (c) {
            jsvObjectSetChild(pipe, "#oncomplete", c);
            jsvUnLock(c);
          }
          c = jsvObjectGetChild(options, "end", false);
          if (c) callEnd = jsvGetBoolAndUnLock(c);
          c = jsvObjectGetChild(options, "chunkSize", false);
          if (c) {
            if (jsvIsNumeric(c) && jsvGetInteger(c)>0)
              chunkSize = jsvGetInteger(c);
            else
              jsWarn("chunkSize must be an integer > 0");
            jsvUnLock(c);
          }
        } else if (!jsvIsUndefined(options)) {
          jsWarn("'options' must be an object, or undefined");
        }
        // set up our event listeners
        jswrap_object_addEventListener(source, "close", jswrap_pipe_src_close_listener, JSWAT_VOID | (JSWAT_JSVAR << (JSWAT_BITS*1)));
        jswrap_object_addEventListener(dest, "drain", jswrap_pipe_drain_listener, JSWAT_VOID | (JSWAT_JSVAR << (JSWAT_BITS*1)));
        jswrap_object_addEventListener(dest, "close", jswrap_pipe_dst_close_listener, JSWAT_VOID | (JSWAT_JSVAR << (JSWAT_BITS*1)));
        // set up the rest of the pipe
        jsvUnLock(jsvObjectSetChild(pipe, "chunkSize", jsvNewFromInteger(chunkSize)));
        jsvUnLock(jsvObjectSetChild(pipe, "end", jsvNewFromBool(callEnd)));
        jsvUnLock(jsvAddNamedChild(pipe, position, "position"));
        jsvUnLock(jsvAddNamedChild(pipe, source, "source"));
        jsvUnLock(jsvAddNamedChild(pipe, dest, "destination"));
        // add the pipe to our list
        jsvArrayPush(arr, pipe);
      } else {
        jsExceptionHere(JSET_ERROR, "Destination object does not implement the required write(buffer, length, position) method.");
      }
    } else {
      jsExceptionHere(JSET_ERROR, "Source object does not implement the required read(buffer, length, position) method.");
    }
    jsvUnLock(readFunc);
    jsvUnLock(writeFunc);
  }
  jsvUnLock(arr);
  jsvUnLock(pipe);
  jsvUnLock(position);
}
Пример #16
0
void serverResponseWriteHead(JsVar *httpServerResponseVar, int statusCode, JsVar *headers) {
    if (!jsvIsUndefined(headers) && !jsvIsObject(headers)) {
        jsError("Headers sent to writeHead should be an object");
        return;
    }

    jsvUnLock(jsvObjectSetChild(httpServerResponseVar, HTTP_NAME_CODE, jsvNewFromInteger(statusCode)));
    JsVar *sendHeaders = jsvObjectGetChild(httpServerResponseVar, HTTP_NAME_HEADERS, 0);
    if (sendHeaders) {
        if (!jsvIsUndefined(headers)) {
            jsvObjectSetChild(httpServerResponseVar, HTTP_NAME_HEADERS, headers);
        }
        jsvUnLock(sendHeaders);
    } else {
        // headers are set to 0 when they are sent
        jsError("Headers have already been sent");
    }
}
Пример #17
0
/*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;
}
Пример #18
0
/*JSON{ "type":"method", "class": "Array", "name" : "join",
         "description" : "Join all elements of this array together into one string, using 'separator' between them. eg. ```[1,2,3].join(' ')=='1 2 3'```",
         "generate" : "jswrap_array_join",
         "params" : [ [ "separator", "JsVar", "The separator"] ],
         "return" : ["JsVar", "A String representing the Joined array"]
}*/
JsVar *jswrap_array_join(JsVar *parent, JsVar *filler) {
  if (jsvIsUndefined(filler))
    filler = jsvNewFromString(","); // the default it seems
  else
    filler = jsvAsString(filler, false);
  if (!filler) return 0; // out of memory
  JsVar *str = jsvArrayJoin(parent, filler);
  jsvUnLock(filler);
  return str;
}
Пример #19
0
static void jswrap_waveform_start(JsVar *waveform, Pin pin, JsVarFloat freq, JsVar *options, bool isWriting) {
  bool running = jsvGetBoolAndUnLock(jsvObjectGetChild(waveform, "running", 0));
  if (running) {
    jsExceptionHere(JSET_ERROR, "Waveform is already running");
    return;
  }
  if (!jshIsPinValid(pin)) {
    jsExceptionHere(JSET_ERROR, "Invalid pin");
    return;
  }
  if (!isfinite(freq) || freq<0.001) {
    jsExceptionHere(JSET_ERROR, "Frequency must be above 0.001Hz");
    return;
  }

  JsSysTime startTime = jshGetSystemTime();
  bool repeat = false;
  if (jsvIsObject(options)) {
    JsVarFloat t = jsvGetFloatAndUnLock(jsvObjectGetChild(options, "time", 0));
    if (isfinite(t) && t>0)
       startTime = jshGetTimeFromMilliseconds(t*1000);
    repeat = jsvGetBoolAndUnLock(jsvObjectGetChild(options, "repeat", 0));
  } else if (!jsvIsUndefined(options)) {
    jsExceptionHere(JSET_ERROR, "Expecting options to be undefined or an Object, not %t", options);
  }

  bool is16Bit = false;
  JsVar *buffer = jswrap_waveform_getBuffer(waveform,0, &is16Bit);
  JsVar *buffer2 = jswrap_waveform_getBuffer(waveform,1,0);

  UtilTimerEventType eventType;

  if (is16Bit) {
    eventType = isWriting ? UET_WRITE_SHORT : UET_READ_SHORT;
  } else {
    eventType = isWriting ? UET_WRITE_BYTE : UET_READ_BYTE;
  }


  // And finally set it up
  if (!jstStartSignal(startTime, jshGetTimeFromMilliseconds(1000.0 / freq), pin, buffer, repeat?(buffer2?buffer2:buffer):0, eventType))
    jsWarn("Unable to schedule a timer");
  jsvUnLock(buffer);
  jsvUnLock(buffer2);

  jsvUnLock(jsvObjectSetChild(waveform, "running", jsvNewFromBool(true)));
  jsvUnLock(jsvObjectSetChild(waveform, "freq", jsvNewFromFloat(freq)));
  // Add to our list of active waveforms
  JsVar *waveforms = jsvObjectGetChild(execInfo.hiddenRoot, JSI_WAVEFORM_NAME, JSV_ARRAY);
  if (waveforms) {
    jsvArrayPush(waveforms, waveform);
    jsvUnLock(waveforms);
  }
}
Пример #20
0
/*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;
  if (pStart<0) pStart += (JsVarInt)jsvGetStringLength(parent);
  if (pStart<0) pStart = 0;
  res = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory
  jsvAppendStringVar(res, parent, (size_t)pStart, (size_t)pLen);
  return res;
}
Пример #21
0
// Connect this connection/socket
void clientRequestConnect(JsNetwork *net, JsVar *httpClientReqVar) {
    // Have we already connected? If so, don't go further
    if (jsvGetIntegerAndUnLock(jsvObjectGetChild(httpClientReqVar, HTTP_NAME_SOCKET, 0))>0)
        return;

    SocketType socketType = socketGetType(httpClientReqVar);

    JsVar *options = jsvObjectGetChild(httpClientReqVar, HTTP_NAME_OPTIONS_VAR, false);
    unsigned short port = (unsigned short)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "port", 0));

    char hostName[128];
    JsVar *hostNameVar = jsvObjectGetChild(options, "host", 0);
    if (jsvIsUndefined(hostNameVar))
        strncpy(hostName, "localhost", sizeof(hostName));
    else
        jsvGetString(hostNameVar, hostName, sizeof(hostName));
    jsvUnLock(hostNameVar);

    uint32_t host_addr = 0;
    networkGetHostByName(net, hostName, &host_addr);

    if(!host_addr) {
        jsError("Unable to locate host\n");
        // As this is already in the list of connections, an error will be thrown on idle anyway
        jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_CLOSENOW, jsvNewFromBool(true));
        jsvUnLock(options);
        netCheckError(net);
        return;
    }

    NetCreateFlags flags = NCF_NORMAL;
#ifdef USE_TLS
    if (socketType & ST_TLS) {
        flags |= NCF_TLS;
        if (port==0) port = 443;
    }
#endif

    if (port==0) port = 80;

    int sckt =  netCreateSocket(net, host_addr, port, flags, options);
    if (sckt<0) {
        jsError("Unable to create socket\n");
        // As this is already in the list of connections, an error will be thrown on idle anyway
        jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_CLOSENOW, jsvNewFromBool(true));
    } else {
        jsvObjectSetChildAndUnLock(httpClientReqVar, HTTP_NAME_SOCKET, jsvNewFromInteger(sckt+1));
    }

    jsvUnLock(options);

    netCheckError(net);
}
Пример #22
0
/*JSON{
  "type" : "function",
  "name" : "trace",
  "ifndef" : "SAVE_ON_FLASH",
  "generate" : "jswrap_interface_trace",
  "params" : [
    ["root","JsVar","The symbol to output (optional). If nothing is specified, everything will be output"]
  ]
}
Output debugging information

Note: This is not included on boards with low amounts of flash memory, or the Espruino board.
 */
void jswrap_interface_trace(JsVar *root) {
  #ifdef ESPRUINOBOARD
  // leave this function out on espruino board - we need to save as much flash as possible
  jsiConsolePrintf("Trace not included on this board");
  #else
  if (jsvIsUndefined(root)) {
    jsvTrace(execInfo.root, 0);
  } else {
    jsvTrace(root, 0);
  }
  #endif
}
Пример #23
0
/*JSON{
  "type" : "method",
  "class" : "ArrayBufferView",
  "name" : "map",
  "generate" : "jswrap_arraybufferview_map",
  "params" : [
    ["function","JsVar","Function used to map one item to another"],
    ["thisArg","JsVar","if specified, the function is called with 'this' set to thisArg (optional)"]
  ],
  "return" : ["JsVar","An array containing the results"],
  "return_object" : "ArrayBufferView"
}
Return an array which is made from the following: ```A.map(function) = [function(A[0]), function(A[1]), ...]```

**Note:** This returns an ArrayBuffer of the same type it was called on. To get an Array, use `Array.prototype.map`
*/
JsVar *jswrap_arraybufferview_map(JsVar *parent, JsVar *funcVar, JsVar *thisVar) {
  if (!jsvIsArrayBuffer(parent)) {
    jsExceptionHere(JSET_ERROR, "ArrayBufferView.map can only be called on an ArrayBufferView");
    return 0;
  }
  if (!jsvIsFunction(funcVar)) {
    jsExceptionHere(JSET_ERROR, "ArrayBufferView.map's first argument should be a function");
    return 0;
  }
  if (!jsvIsUndefined(thisVar) && !jsvIsObject(thisVar)) {
    jsExceptionHere(JSET_ERROR, "ArrayBufferView.map's second argument should be undefined, or an object");
    return 0;
  }

  // create ArrayBuffer result
  JsVarDataArrayBufferViewType arrayBufferType = parent->varData.arraybuffer.type;
  JsVar *arrayBufferLength = jsvNewFromInteger((JsVarInt)jsvGetArrayBufferLength(parent));
  JsVar *array = jswrap_typedarray_constructor(arrayBufferType, arrayBufferLength, 0, 0);
  jsvUnLock(arrayBufferLength);
  if (!array) return 0;

  // now iterate
  JsvIterator it; // TODO: if we really are limited to ArrayBuffers, this could be an ArrayBufferIterator.
  jsvIteratorNew(&it, parent);
  JsvArrayBufferIterator itdst;
  jsvArrayBufferIteratorNew(&itdst, array, 0);

  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) {
        jsvArrayBufferIteratorSetValue(&itdst, mapped);
        jsvUnLock(mapped);
      }
    }
    jsvUnLock(index);
    jsvIteratorNext(&it);
    jsvArrayBufferIteratorNext(&itdst);
  }
  jsvIteratorFree(&it);
  jsvArrayBufferIteratorFree(&itdst);

  return array;
}
Пример #24
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "match",
  "generate" : "jswrap_string_match",
  "params" : [
    ["subStr","JsVar","Substring or RegExp to match"]
  ],
  "return" : ["JsVar","This match array"]
}
Matches `subStr` occurrence in the string.
 */
JsVar *jswrap_string_match(JsVar *parent, JsVar *subStr) {
  if (!jsvIsString(parent)) return 0;
  if (jsvIsUndefined(subStr)) return 0;

#ifndef SAVE_ON_FLASH
  // Use RegExp if one is passed in
  if (jsvIsInstanceOf(subStr, "RegExp")) {
    jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    JsVar *match;
    match = jswrap_regexp_exec(subStr, parent);
    if (!jswrap_regexp_hasFlag(subStr,'g')) {
      return match;
    }

    // global
    JsVar *array = jsvNewEmptyArray();
    if (!array) return 0; // out of memory
    while (match && !jsvIsNull(match)) {
      // get info about match
      JsVar *matchStr = jsvGetArrayItem(match,0);
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvObjectGetChild(match,"index",0));
      JsVarInt len = (JsVarInt)jsvGetStringLength(matchStr);
      int last = idx+len;
      jsvArrayPushAndUnLock(array, matchStr);
      // search again
      jsvUnLock(match);
      jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(last));
      match = jswrap_regexp_exec(subStr, parent);
    }
    jsvUnLock(match);
    jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    return array;
  }
#endif

  subStr = jsvAsString(subStr);

  int idx = jswrap_string_indexOf(parent, subStr, 0, false);
  if (idx>=0) {
      JsVar *array = jsvNewEmptyArray();
      if (!array) {
        jsvUnLock(subStr);
        return 0; // out of memory
      }

      jsvArrayPush(array, subStr);
      jsvObjectSetChildAndUnLock(array, "index", jsvNewFromInteger(idx));
      jsvObjectSetChildAndUnLock(array, "input", subStr);
      return array;
  }
  jsvUnLock(subStr);
  return NULL;
}
Пример #25
0
/*JSON{ "type":"method", "class": "Array", "name" : "slice",
         "description" : "Return a copy of a portion of the calling array",
         "generate" : "jswrap_array_slice",
         "params" : [ [ "start", "JsVar", "Start index"],
                      [ "end", "JsVar", "End index (optional)"] ],
         "return" : ["JsVar", "A new array"]
}*/
JsVar *jswrap_array_slice(JsVar *parent, JsVar *startVar, JsVar *endVar) {
  JsVarInt len = jsvGetLength(parent);
  JsVarInt start = 0;
  JsVarInt end = len;

  if (!jsvIsUndefined(startVar))
    start = jsvGetInteger(startVar);

  if (!jsvIsUndefined(endVar))
    end = jsvGetInteger(endVar);

  JsVarInt k = 0;
  JsVarInt final = len;
  JsVar *array = jsvNewWithFlags(JSV_ARRAY);

  if (!array) return 0;

  if (start<0) k = max((len + start), 0);
  else k = min(start, len);

  if (end<0) final = max((len + end), 0);
  else final = min(end, len);
Пример #26
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "slice",
  "generate" : "jswrap_string_slice",
  "params" : [
    ["start","int","The start character index, if negative it is from the end of the string"],
    ["end","JsVar","The end character index, if negative it is from the end of the string, and if omitted it is the end of the string"]
  ],
  "return" : ["JsVar","Part of this string from start for len characters"]
}*/
JsVar *jswrap_string_slice(JsVar *parent, JsVarInt pStart, JsVar *vEnd) {
  JsVar *res;
  JsVarInt pEnd = jsvIsUndefined(vEnd) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vEnd);
  if (pStart<0) pStart += (JsVarInt)jsvGetStringLength(parent);
  if (pEnd<0) pEnd += (JsVarInt)jsvGetStringLength(parent);
  if (pStart<0) pStart = 0;
  if (pEnd<0) pEnd = 0;
  res = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory
  if (pEnd>pStart)
    jsvAppendStringVar(res, parent, (size_t)pStart, (size_t)(pEnd-pStart));
  return res;
}
Пример #27
0
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;
}
Пример #28
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "ping",
  "generate" : "jswrap_ESP8266WiFi_ping",
  "params"   : [
    ["ipAddr","JsVar","A string or integer representation of an IP address."],
    ["pingCallback", "JsVar", "Optional callback function."]
  ]
}*/
void jswrap_ESP8266WiFi_ping(
    JsVar *ipAddr,      //!< A string or integer representation of an IP address.
    JsVar *pingCallback //!< Optional callback function.
  ) {
  // If the parameter is a string, get the IP address from the string
  // representation.
  if (jsvIsString(ipAddr)) {
    char ipString[20];
    int len = jsvGetString(ipAddr, ipString, sizeof(ipString)-1);
    ipString[len] = '\0';
    pingOpt.ip = networkParseIPAddress(ipString);
    if (pingOpt.ip == 0) {
        jsExceptionHere(JSET_ERROR, "Not a valid IP address.");
      return;
    }
  } else
  // If the parameter is an integer, treat it as an IP address.
  if (jsvIsInt(ipAddr)) {
    pingOpt.ip = jsvGetInteger(ipAddr);
  } else
  // The parameter was neither a string nor an IP address and hence we don't
  // know how to get the IP address of the partner to ping so throw an
  // exception.
  {
      jsExceptionHere(JSET_ERROR, "IP address must be string or integer.");
    return;
  }

  if (jsvIsUndefined(pingCallback) || jsvIsNull(pingCallback)) {
    if (g_jsPingCallback != NULL) {
      jsvUnLock(g_jsPingCallback);
    }
    g_jsPingCallback = NULL;
  } else if (!jsvIsFunction(pingCallback)) {
      jsExceptionHere(JSET_ERROR, "Callback is not a function.");
    return;
  } else {
    if (g_jsPingCallback != NULL) {
      jsvUnLock(g_jsPingCallback);
    }
    g_jsPingCallback = pingCallback;
    jsvLockAgainSafe(g_jsPingCallback);
  }

  // We now have an IP address to ping ... so ping.
  memset(&pingOpt, 0, sizeof(pingOpt));
  pingOpt.count = 5;
  pingOpt.recv_function = pingRecvCB;
  ping_start(&pingOpt);
}
Пример #29
0
/*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 = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory
  jsvAppendStringVar(res, parent, (size_t)pStart, (size_t)(pEnd-pStart));
  return res;
}
Пример #30
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "on",
  "generate" : "jswrap_object_on",
  "params" : [
    ["event","JsVar","The name of the event, for instance 'data'"],
    ["listener","JsVar","The listener to call when this event is received"]
  ]
}
Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter.
 */
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
  if (!jsvHasChildren(parent)) {
    jsWarn("Parent must be an object - not a String, Integer, etc.");
    return;
  }
  if (!jsvIsString(event)) {
    jsWarn("First argument to EventEmitter.on(..) must be a string");
    return;
  }
  if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
    jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
    return;
  }

  JsVar *eventName = jsvVarPrintf(JS_EVENT_PREFIX"%s",event);
  if (!eventName) return; // no memory

  JsVar *eventList = jsvFindChildFromVar(parent, eventName, true);
  jsvUnLock(eventName);
  JsVar *eventListeners = jsvSkipName(eventList);
  if (jsvIsUndefined(eventListeners)) {
    // just add
    jsvSetValueOfName(eventList, listener);
  } else {
    if (jsvIsArray(eventListeners)) {
      // we already have an array, just add to it
      jsvArrayPush(eventListeners, listener);
    } else {
      // not an array - we need to make it an array
      JsVar *arr = jsvNewEmptyArray();
      jsvArrayPush(arr, eventListeners);
      jsvArrayPush(arr, listener);
      jsvSetValueOfName(eventList, arr);
      jsvUnLock(arr);
    }
  }
  jsvUnLock2(eventListeners, eventList);
  /* Special case if we're a data listener and data has already arrived then
   * we queue an event immediately. */
  if (jsvIsStringEqual(event, "data")) {
    JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
    if (jsvIsString(buf)) {
      jsiQueueObjectCallbacks(parent, STREAM_CALLBACK_NAME, &buf, 1);
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    }
    jsvUnLock(buf);
  }
}